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