001package jmri.jmrit.beantable.beanedit;
002
003import java.awt.event.ActionEvent;
004
005import javax.swing.*;
006
007import jmri.*;
008import jmri.NamedBean.DisplayOptions;
009import jmri.implementation.SignalSpeedMap;
010import jmri.jmrit.beantable.block.BlockCurvatureJComboBox;
011import jmri.jmrit.beantable.oblock.TableFrames;
012import jmri.jmrit.logix.OBlock;
013import jmri.jmrit.logix.OBlockManager;
014import jmri.swing.NamedBeanComboBox;
015import jmri.util.swing.JComboBoxUtil;
016
017/**
018 * Provides a tabbed beanedit panel for an OBlock object.
019 *
020 * @author Kevin Dickerson Copyright (C) 2011
021 * @author Egbert Broerse Copyright (C) 2020
022 */
023public class OBlockEditAction extends BeanEditAction<OBlock> {
024
025    static final java.util.Vector<String> speedList = new java.util.Vector<>();
026    private String tabName = Bundle.getMessage("BeanNameOBlock");
027    NamedBeanComboBox<Reporter> reporterComboBox;
028    JCheckBox useCurrent = new JCheckBox();
029    TableFrames.BlockPathJPanel blockPathPanel;
030    NamedBeanComboBox<Sensor> sensorComboBox;
031    NamedBeanComboBox<Sensor> errorSensorComboBox;
032
033    public OBlockEditAction(ActionEvent ae) {
034        super();
035        if (ae != null) {
036            tabName = ae.getActionCommand();
037        }
038    }
039
040    @Override
041    public String helpTarget() {
042        return "package.jmri.jmrit.beantable.OBlockTable";
043    } // NOI18N
044
045    public void setTablePanel(TableFrames.BlockPathJPanel panel){
046        blockPathPanel = panel;
047    }
048
049    @Override
050    protected void initPanels() {
051        super.initPanels();
052        sensor();
053        paths();
054        reporterDetails();
055        physicalDetails();
056    }
057
058    @Override
059    public OBlock getByUserName(String name) {
060        return InstanceManager.getDefault(OBlockManager.class).getByUserName(name);
061    }
062
063    BeanItemPanel sensor() {
064        BeanItemPanel basic = new BeanItemPanel();
065        basic.setName(Bundle.getMessage("BeanNameSensors"));
066
067        sensorComboBox = new NamedBeanComboBox<>(InstanceManager.sensorManagerInstance(), bean.getSensor(), DisplayOptions.DISPLAYNAME);
068        sensorComboBox.setAllowNull(true);
069        JComboBoxUtil.setupComboBoxMaxRows(sensorComboBox);
070        basic.addItem(new BeanEditItem(sensorComboBox, Bundle.getMessage("BeanNameSensor"), Bundle.getMessage("BlockAssignSensorText")));
071
072        errorSensorComboBox = new NamedBeanComboBox<>(InstanceManager.sensorManagerInstance(), bean.getSensor(), DisplayOptions.DISPLAYNAME);
073        errorSensorComboBox.setAllowNull(true);
074        JComboBoxUtil.setupComboBoxMaxRows(errorSensorComboBox);
075        basic.addItem(new BeanEditItem(errorSensorComboBox, Bundle.getMessage("ErrorSensorCol"), Bundle.getMessage("BlockAssignErrorSensorText")));
076
077        final SensorDebounceEditAction debounce = new SensorDebounceEditAction();
078        debounce.sensorDebounce(basic);
079
080        sensorComboBox.addActionListener(e -> {
081            debounce.setBean(sensorComboBox.getSelectedItem());
082            debounce.resetDebounceItems(e);
083        });
084        basic.setSaveItem(new AbstractAction() {
085            @Override
086            public void actionPerformed(ActionEvent e) {
087                if (sensorComboBox.getSelectedItem() == null) {
088                    bean.setSensor(null);
089                } else {
090                    bean.setSensor(sensorComboBox.getSelectedItem().getDisplayName());
091                }
092                if (errorSensorComboBox.getSelectedItem() == null) {
093                    bean.setErrorSensor(null);
094                } else {
095                    bean.setErrorSensor(errorSensorComboBox.getSelectedItem().getDisplayName());
096                }
097            }
098        });
099        basic.setResetItem(new AbstractAction() {
100            @Override
101            public void actionPerformed(ActionEvent e) {
102                //From basic details
103                sensorComboBox.setSelectedItem(bean.getSensor());
104                errorSensorComboBox.setSelectedItem(bean.getErrorSensor());
105                debounce.setBean(bean.getSensor());
106                debounce.resetDebounceItems(e);
107            }
108        });
109
110        bei.add(basic);
111        return basic;
112    }
113
114    BeanItemPanel paths() {
115        BeanItemPanel paths = new BeanItemPanel();
116        String name = Bundle.getMessage("TitlePaths");
117        paths.setName(name);
118
119        paths.addItem(new BeanEditItem(blockPathPanel, Bundle.getMessage("PathTableLabel", bean.getDisplayName()), null));
120        // includes Add Path button
121
122        paths.setResetItem(new AbstractAction() {
123            @Override
124            public void actionPerformed(ActionEvent e) {
125                //clear the table?
126            }
127        });
128
129        bei.add(paths);
130        if (InstanceManager.getNullableDefault(OBlockManager.class) == null) {
131            setEnabled(false);
132        }
133        if (name.equals(tabName)) {
134            setSelectedComponent(paths);
135        }
136        return paths;
137    }
138
139    BeanItemPanel reporterDetails() {
140        BeanItemPanel reporter = new BeanItemPanel();
141        reporter.setName(Bundle.getMessage("BeanNameReporter"));
142
143        reporterComboBox = new NamedBeanComboBox<>(InstanceManager.getDefault(ReporterManager.class), bean.getReporter(), DisplayOptions.DISPLAYNAME);
144        reporterComboBox.setAllowNull(true);
145        JComboBoxUtil.setupComboBoxMaxRows(reporterComboBox);
146
147        reporter.addItem(new BeanEditItem(reporterComboBox, Bundle.getMessage("BeanNameReporter"), Bundle.getMessage("BlockReporterText")));
148
149        reporterComboBox.addActionListener(e -> useCurrent.setEnabled(reporterComboBox.getSelectedItem() != null));
150
151        reporter.addItem(new BeanEditItem(useCurrent, Bundle.getMessage("BlockReporterCurrent"), Bundle.getMessage("BlockUseCurrentText")));
152
153        reporter.setResetItem(new AbstractAction() {
154            @Override
155            public void actionPerformed(ActionEvent e) {
156                reporterComboBox.setSelectedItem(bean.getReporter());
157                useCurrent.setSelected(bean.isReportingCurrent());
158                useCurrent.setEnabled(bean.getReporter()!=null);
159            }
160        });
161
162        reporter.setSaveItem(new AbstractAction() {
163            @Override
164            public void actionPerformed(ActionEvent e) {
165                bean.setReporter(reporterComboBox.getSelectedItem());
166                bean.setReportingCurrent(useCurrent.isSelected());
167            }
168        });
169        bei.add(reporter);
170        if (InstanceManager.getNullableDefault(ReporterManager.class) == null) {
171            setEnabled(false);
172        }
173        return reporter;
174    }
175
176    JSpinner lengthSpinner = new JSpinner(); // 2 digit decimal format field, initialized later as instance
177    private final BlockCurvatureJComboBox curvatureField = new BlockCurvatureJComboBox();
178    JCheckBox permissiveField = new JCheckBox();
179    JComboBox<String> speedField;
180
181    JRadioButton inch = new JRadioButton(Bundle.getMessage("LengthInches"));
182    JRadioButton cm = new JRadioButton(Bundle.getMessage("LengthCentimeters"));
183
184    String defaultBlockSpeedText;
185
186    BeanItemPanel physicalDetails() {
187        defaultBlockSpeedText = (Bundle.getMessage("UseGlobal", "Global") + " " + InstanceManager.getDefault(BlockManager.class).getDefaultSpeed());
188        speedList.add(defaultBlockSpeedText);
189        java.util.Vector<String> _speedMap = InstanceManager.getDefault(SignalSpeedMap.class).getValidSpeedNames();
190        for (String s : _speedMap) {
191            if (!speedList.contains(s)) {
192                speedList.add(s);
193            }
194        }
195        BeanItemPanel basic = new BeanItemPanel();
196        basic.setName(Bundle.getMessage("BlockPhysicalProperties"));
197
198        basic.addItem(new BeanEditItem(null, null, Bundle.getMessage("BlockPropertiesText")));
199        lengthSpinner.setModel(
200                            new SpinnerNumberModel(Float.valueOf(0f), Float.valueOf(0f), Float.valueOf(1000f), Float.valueOf(0.01f)));
201        lengthSpinner.setEditor(new JSpinner.NumberEditor(lengthSpinner, "###0.00"));
202        lengthSpinner.setPreferredSize(new JTextField(8).getPreferredSize());
203        lengthSpinner.setValue(0f); // reset from possible previous use
204        basic.addItem(new BeanEditItem(lengthSpinner, Bundle.getMessage("BlockLengthColName"), Bundle.getMessage("BlockLengthText")));
205
206        ButtonGroup rg = new ButtonGroup();
207        rg.add(inch);
208        rg.add(cm);
209
210        JPanel p = new JPanel();
211        p.add(inch);
212        p.add(cm);
213        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
214        inch.setSelected(true);
215
216        inch.addActionListener(e -> {
217            cm.setSelected(!inch.isSelected());
218            updateLength();
219        });
220        cm.addActionListener(e -> {
221            inch.setSelected(!cm.isSelected());
222            updateLength();
223        });
224
225        speedField = new JComboBox<>(speedList);
226        JComboBoxUtil.setupComboBoxMaxRows(speedField);
227        basic.addItem(new BeanEditItem(p, Bundle.getMessage("BlockLengthUnits"), Bundle.getMessage("BlockLengthUnitsText")));
228        basic.addItem(new BeanEditItem(curvatureField, Bundle.getMessage("BlockCurveColName"), ""));
229        basic.addItem(new BeanEditItem(speedField, Bundle.getMessage("BlockSpeedColName"), Bundle.getMessage("BlockMaxSpeedText")));
230        basic.addItem(new BeanEditItem(permissiveField, Bundle.getMessage("BlockPermColName"), Bundle.getMessage("BlockPermissiveText")));
231
232        permissiveField.setSelected(bean.getPermissiveWorking());
233
234        basic.setSaveItem(new AbstractAction() {
235            @Override
236            public void actionPerformed(ActionEvent e) {
237                bean.setCurvature(curvatureField.getCurvature());
238
239                String speed = (String) speedField.getSelectedItem();
240                try {
241                    bean.setBlockSpeed(speed);
242                } catch (JmriException ex) {
243                    jmri.util.swing.JmriJOptionPane.showMessageDialog(f, ex.getMessage() + "\n" + speed);
244                    return;
245                }
246                if (speed != null && !speedList.contains(speed) && !speed.contains("Global")) {
247                    speedList.add(speed);
248                }
249                float len = (Float) lengthSpinner.getValue();
250                bean.setLength( inch.isSelected() ? (len * 25.4f) : (len * 10.0f) );
251                bean.setPermissiveWorking(permissiveField.isSelected());
252            }
253        });
254        basic.setResetItem(new AbstractAction() {
255            @Override
256            public void actionPerformed(ActionEvent e) {
257                lengthSpinner.setValue(bean.getLengthMm());
258
259                curvatureField.setCurvature(bean.getCurvature());
260
261                String speed = bean.getBlockSpeed();
262                if (!speedList.contains(speed)) {
263                    speedList.add(speed);
264                }
265
266                speedField.setEditable(true);
267                speedField.setSelectedItem(speed);
268                updateLength();
269                permissiveField.setSelected(bean.getPermissiveWorking());
270            }
271        });
272        bei.add(basic);
273        return basic;
274    }
275
276    private void updateLength() {
277        lengthSpinner.setValue(inch.isSelected() ? bean.getLengthIn() : bean.getLengthCm());
278    }
279
280    // private final static Logger log = LoggerFactory.getLogger(OBlockEditAction.class);
281
282}