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.BlockTableAction;
011import jmri.jmrit.beantable.block.BlockCurvatureJComboBox;
012import jmri.jmrit.display.layoutEditor.LayoutBlock;
013import jmri.jmrit.display.layoutEditor.LayoutBlockManager;
014import jmri.swing.NamedBeanComboBox;
015import jmri.util.swing.JComboBoxUtil;
016
017/**
018 * Provides an edit panel for a Block object.
019 * Note that LayoutBlockEditAction extends this class, so please check
020 * this still functions as expected when making changes here.
021 *
022 * @author Kevin Dickerson Copyright (C) 2011
023 */
024public class BlockEditAction extends BeanEditAction<Block> {
025
026    static final java.util.Vector<String> speedList = new java.util.Vector<>();
027
028    @Override
029    public String helpTarget() {
030        return "package.jmri.jmrit.beantable.BlockEdit";
031    } // NOI18N
032
033    @Override
034    protected void initPanels() {
035        super.initPanels();
036        sensor();
037        reporterDetails();
038        physicalDetails();
039    }
040
041    @Override
042    public Block getByUserName(String name) {
043        return InstanceManager.getDefault(BlockManager.class).getByUserName(name);
044    }
045
046    private NamedBeanComboBox<Reporter> reporterComboBox;
047    private JCheckBox useCurrent = new JCheckBox();
048
049    private JSpinner lengthSpinner = new JSpinner(); // 2 digit decimal format field, initialized later as instance
050    private BlockCurvatureJComboBox curvatureField = new BlockCurvatureJComboBox();
051    private JCheckBox permissiveField = new JCheckBox();
052    private JComboBox<String> speedField;
053
054    JRadioButton inch = new JRadioButton(Bundle.getMessage("LengthInches"));
055    JRadioButton cm = new JRadioButton(Bundle.getMessage("LengthCentimeters"));
056
057    private String defaultBlockSpeedText;
058
059    protected boolean metricUi = InstanceManager.getDefault(UserPreferencesManager.class)
060        .getSimplePreferenceState(BlockTableAction.BLOCK_METRIC_PREF);
061
062    BeanItemPanel reporterDetails() {
063        BeanItemPanel reporter = new BeanItemPanel();
064        reporter.setName(Bundle.getMessage("BeanNameReporter"));
065
066        reporterComboBox = new NamedBeanComboBox<>(InstanceManager.getDefault(ReporterManager.class), bean.getReporter(), DisplayOptions.DISPLAYNAME);
067        reporterComboBox.setAllowNull(true);
068        JComboBoxUtil.setupComboBoxMaxRows(reporterComboBox);
069
070        reporter.addItem(new BeanEditItem(reporterComboBox, Bundle.getMessage("BeanNameReporter"), Bundle.getMessage("BlockReporterText")));
071
072        reporterComboBox.addActionListener((ActionEvent e) -> {
073            useCurrent.setEnabled(reporterComboBox.getSelectedItem() != null);
074        });
075
076        reporter.addItem(new BeanEditItem(useCurrent, Bundle.getMessage("BlockReporterCurrent"), Bundle.getMessage("BlockUseCurrentText")));
077
078        reporter.setResetItem(new AbstractAction() {
079            @Override
080            public void actionPerformed(ActionEvent e) {
081                reporterComboBox.setSelectedItem(bean.getReporter());
082                useCurrent.setSelected(bean.isReportingCurrent());
083                useCurrent.setEnabled(bean.getReporter()!=null);
084            }
085        });
086
087        reporter.setSaveItem(new AbstractAction() {
088            @Override
089            public void actionPerformed(ActionEvent e) {
090                bean.setReporter(reporterComboBox.getSelectedItem());
091                bean.setReportingCurrent(useCurrent.isSelected());
092            }
093        });
094        bei.add(reporter);
095        if (InstanceManager.getNullableDefault(ReporterManager.class) == null) {
096            setEnabled(false);
097        }
098        return reporter;
099    }
100
101    BeanItemPanel physicalDetails() {
102
103        defaultBlockSpeedText = (Bundle.getMessage("UseGlobal", "Global") + " " + InstanceManager.getDefault(BlockManager.class).getDefaultSpeed());
104        speedList.add(defaultBlockSpeedText);
105        java.util.Vector<String> _speedMap = InstanceManager.getDefault(SignalSpeedMap.class).getValidSpeedNames();
106        for (int i = 0; i < _speedMap.size(); i++) {
107            if (!speedList.contains(_speedMap.get(i))) {
108                speedList.add(_speedMap.get(i));
109            }
110        }
111        BeanItemPanel basic = new BeanItemPanel();
112        basic.setName(Bundle.getMessage("BlockPhysicalProperties"));
113
114        basic.addItem(new BeanEditItem(null, null, Bundle.getMessage("BlockPropertiesText")));
115        lengthSpinner.setModel(
116                            new SpinnerNumberModel(Float.valueOf(0f), Float.valueOf(0f), Float.valueOf(1000f), Float.valueOf(0.01f)));
117        lengthSpinner.setEditor(new JSpinner.NumberEditor(lengthSpinner, "###0.00"));
118        lengthSpinner.setPreferredSize(new JTextField(8).getPreferredSize());
119
120        ButtonGroup rg = new ButtonGroup();
121        rg.add(inch);
122        rg.add(cm);
123
124        JPanel p = new JPanel();
125        p.add(inch);
126        p.add(cm);
127        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
128        inch.setSelected(!metricUi);
129        cm.setSelected(metricUi);
130        inch.addActionListener(this::updateLength);
131        cm.addActionListener(this::updateLength);
132
133        basic.addItem(new BeanEditItem(lengthSpinner, Bundle.getMessage("BlockLengthColName"), Bundle.getMessage("BlockLengthText") ));
134        basic.addItem(new BeanEditItem(p, Bundle.getMessage("BlockLengthUnits"), Bundle.getMessage("BlockLengthUnitsText")));
135        basic.addItem(new BeanEditItem(curvatureField, Bundle.getMessage("BlockCurveColName"), ""));
136        speedField = new JComboBox<>(speedList);
137        JComboBoxUtil.setupComboBoxMaxRows(speedField);
138        basic.addItem(new BeanEditItem(speedField, Bundle.getMessage("BlockSpeedColName"), Bundle.getMessage("BlockMaxSpeedText")));
139        basic.addItem(new BeanEditItem(permissiveField, Bundle.getMessage("BlockPermColName"), Bundle.getMessage("BlockPermissiveText")));
140
141        permissiveField.setSelected(bean.getPermissiveWorking());
142
143        basic.setSaveItem(new AbstractAction() {
144            @Override
145            public void actionPerformed(ActionEvent e) {
146                bean.setCurvature(curvatureField.getCurvature());
147                String speed = (String) speedField.getSelectedItem();
148                try {
149                    bean.setBlockSpeed(speed);
150                } catch (JmriException ex) {
151                    jmri.util.swing.JmriJOptionPane.showMessageDialog(f, ex.getMessage() + "\n" + speed);
152                    return;
153                }
154                if (!speedList.contains(speed) && !speed.contains("Global")) {
155                    speedList.add(speed);
156                }
157                float len = (Float) lengthSpinner.getValue();
158                bean.setLength( metricUi ? len * 10.0f : len * 25.4f);
159                bean.setPermissiveWorking(permissiveField.isSelected());
160            }
161        });
162        basic.setResetItem(new AbstractAction() {
163            @Override
164            public void actionPerformed(ActionEvent e) {
165                curvatureField.setCurvature(bean.getCurvature());
166                String speed = bean.getBlockSpeed();
167                if (!speedList.contains(speed)) {
168                    speedList.add(speed);
169                }
170                speedField.setEditable(true);
171                speedField.setSelectedItem(speed);
172                updateLength(e);
173                permissiveField.setSelected(bean.getPermissiveWorking());
174            }
175        });
176        bei.add(basic);
177        return basic;
178    }
179
180    private void updateLength(ActionEvent e) {
181        metricUi = cm.isSelected();
182        lengthSpinner.setValue(metricUi ?  bean.getLengthCm() : bean.getLengthIn());
183    }
184
185    NamedBeanComboBox<Sensor> sensorComboBox;
186
187    BeanItemPanel sensor() {
188
189        BeanItemPanel basic = new BeanItemPanel();
190        basic.setName(Bundle.getMessage("BeanNameSensor"));
191
192        sensorComboBox = new NamedBeanComboBox<>(InstanceManager.sensorManagerInstance(), bean.getSensor(), DisplayOptions.DISPLAYNAME);
193        sensorComboBox.setAllowNull(true);
194        JComboBoxUtil.setupComboBoxMaxRows(sensorComboBox);
195        basic.addItem(new BeanEditItem(sensorComboBox, Bundle.getMessage("BeanNameSensor"), Bundle.getMessage("BlockAssignSensorText")));
196
197        final SensorDebounceEditAction debounce = new SensorDebounceEditAction();
198        //debounce.setBean(bean);
199        debounce.sensorDebounce(basic);
200
201        sensorComboBox.addActionListener((ActionEvent e) -> {
202            debounce.setBean(sensorComboBox.getSelectedItem());
203            debounce.resetDebounceItems(e);
204        });
205
206        basic.setSaveItem(new AbstractAction() {
207            @Override
208            public void actionPerformed(ActionEvent e) {
209                LayoutBlock lBlk = InstanceManager.getDefault(LayoutBlockManager.class).getLayoutBlock(bean);
210                //If the block is related to a layoutblock then set the sensor details there and allow that to propagate the changes down.
211                if (lBlk != null) {
212                    lBlk.validateSensor(sensorComboBox.getSelectedItemDisplayName(), null);
213                } else {
214                    bean.setSensor(sensorComboBox.getSelectedItemDisplayName());
215                }
216                debounce.saveDebounceItems(e);
217            }
218        });
219        basic.setResetItem(new AbstractAction() {
220            @Override
221            public void actionPerformed(ActionEvent e) {
222                //From basic details
223                sensorComboBox.setSelectedItem(bean.getSensor());
224                debounce.setBean(bean.getSensor());
225                debounce.resetDebounceItems(e);
226            }
227        });
228
229        bei.add(basic);
230        return basic;
231    }
232
233    // private final static Logger log = LoggerFactory.getLogger(BlockEditAction.class);
234
235}