001package jmri.jmrix.can.cbus.swing.modules.base;
002
003import java.awt.*;
004
005import javax.swing.*;
006import javax.swing.event.*;
007
008import jmri.jmrix.can.cbus.node.CbusNode;
009import jmri.jmrix.can.cbus.node.CbusNodeNVTableDataModel;
010import jmri.jmrix.can.cbus.swing.modules.*;
011import static jmri.jmrix.can.cbus.swing.modules.merg.CansolPaneProvider.*;
012
013/**
014 * Node Variable edit frame for a basic 8-channel solenoid module
015 *
016 * @author Andrew Crosland Copyright (C) 2021
017 */
018public class Sol8BaseEditNVPane extends AbstractEditNVPane {
019    
020    // Number of outputs
021    public static final int OUTPUTS = 8;
022    
023    // Conversion between NV and display values
024    public static final int TIME_STEP_SIZE = 10;
025    
026    private final UpdateNV pulseUpdateFn = new UpdatePulse();
027    private final UpdateNV rechargeUpdateFn = new UpdateRecharge();
028    private final UpdateNV fireDelayUpdateFn = new UpdateFireDelay();
029    private final UpdateNV enableDelayUpdateFn = new UpdateEnableDelay();
030
031    private TitledSpinner pulse[] = new TitledSpinner[OUTPUTS + 1];
032    private TitledSpinner rechargeSpinner;
033    private TitledSpinner fireDelaySpinner;
034    private TitledSpinner enableDelaySpinner;
035    
036    protected Sol8BaseEditNVPane(CbusNodeNVTableDataModel dataModel, CbusNode node) {
037        super(dataModel, node);
038        initSpinners();
039    }
040
041    private void initSpinners() {
042
043        rechargeSpinner = new TitledSpinner(Bundle.getMessage("RechargeTimeUnits"), RECHARGE_TIME, rechargeUpdateFn);
044        rechargeSpinner.setToolTip(Bundle.getMessage("RechargeTimeTt"));
045        
046        fireDelaySpinner = new TitledSpinner(Bundle.getMessage("FireDelayUnits"), FIRE_DELAY, fireDelayUpdateFn);
047        fireDelaySpinner.setToolTip(Bundle.getMessage("FireDelayTt"));
048
049        enableDelaySpinner = new TitledSpinner(Bundle.getMessage("EnableDelayUnits"), ENABLE_DELAY, enableDelayUpdateFn);
050        enableDelaySpinner.setToolTip(Bundle.getMessage("EnableDelayTt"));
051    }
052    
053    /** {@inheritDoc} */
054    @Override
055    public AbstractEditNVPane getContent() {
056       
057        JPanel gridPane = new JPanel(new GridBagLayout());
058        GridBagConstraints c = new GridBagConstraints();
059        c.fill = GridBagConstraints.HORIZONTAL;
060        c.weightx = 1;
061        c.weighty = 1;
062        c.gridy = 0;
063        
064        // Four columns for the outputs
065        for (int y = 0; y < OUTPUTS/4; y++) {
066            c.gridx = 0;
067            for (int x = 0; x < 4; x++) {
068                int index = y*4 + x + 1;            // NVs indexed from 1
069                pulse[index] = new TitledSpinner((Bundle.getMessage("OutputX", index)) + " " + Bundle.getMessage("PulseWidthUnits"), index, pulseUpdateFn);
070                pulse[index].setToolTip(Bundle.getMessage("CanSolOutputTt"));
071                pulse[index].init(getSelectValue8(index)*TIME_STEP_SIZE, 0, TIME_STEP_SIZE*255, TIME_STEP_SIZE);
072                gridPane.add(pulse[index], c);
073                c.gridx++;
074            }
075            c.gridy++;
076        }
077
078        c.gridx = 0;
079        
080        rechargeSpinner.init(getSelectValue8(RECHARGE_TIME)*TIME_STEP_SIZE, 0, TIME_STEP_SIZE*255, TIME_STEP_SIZE);
081        
082        gridPane.add(rechargeSpinner, c);
083        c.gridx++;
084
085        fireDelaySpinner.init(getSelectValue8(FIRE_DELAY)*TIME_STEP_SIZE, 0, TIME_STEP_SIZE*255, TIME_STEP_SIZE);
086        
087        gridPane.add(fireDelaySpinner, c);
088        c.gridx++;
089
090        enableDelaySpinner.init(getSelectValue8(ENABLE_DELAY)*TIME_STEP_SIZE, 0, TIME_STEP_SIZE*255, TIME_STEP_SIZE);
091        
092        gridPane.add(enableDelaySpinner, c);
093
094        JScrollPane scroll = new JScrollPane(gridPane);
095        add(scroll);
096        
097        return this;
098    }
099    
100    /** {@inheritDoc} */
101    @Override
102    public void tableChanged(TableModelEvent e) {
103        if (e.getType() == TableModelEvent.UPDATE) {
104            int row = e.getFirstRow();
105            int nv = row + 1;
106            int value = getSelectValue8(nv);
107            if ((nv > 0) && (nv <= 8)) {
108                //log.debug("Update NV {} to {}", nv, value);
109                pulse[nv].setValue(value*TIME_STEP_SIZE);
110            } else if (nv == 9) {
111                //log.debug("Update recharge delay to {}", value);
112                rechargeSpinner.setValue(value*TIME_STEP_SIZE);
113            } else if (nv == 10) {
114                //log.debug("Update fire delay to {}", value);
115                fireDelaySpinner.setValue(value*TIME_STEP_SIZE);
116            } else if (nv == 11) {
117                //log.debug("Update enable delay to {}", value);
118                enableDelaySpinner.setValue(value*TIME_STEP_SIZE);
119            } else {
120                // Not used, or row was -1
121//                log.debug("Update unknown NV {}", nv);
122            }
123        }
124    }
125    
126    /**
127     * Update the NV controlling the output pulse width
128     */
129    protected class UpdatePulse implements UpdateNV {
130
131        /** {@inheritDoc} */
132        @Override
133        public void setNewVal(int index) {
134            int delay = pulse[index].getIntegerValue()/TIME_STEP_SIZE;
135            // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc
136            _dataModel.setValueAt(delay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN);
137        }
138    }
139    
140    /**
141     * Update the NV controlling the recharge delay
142     */
143    protected class UpdateRecharge implements UpdateNV {
144
145        /** {@inheritDoc} */
146        @Override
147        public void setNewVal(int index) {
148            int delay = rechargeSpinner.getIntegerValue()/TIME_STEP_SIZE;
149            // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc
150            _dataModel.setValueAt(delay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN);
151        }
152    }
153    
154    /**
155     * Update the NV controlling the recharge delay
156     */
157    protected class UpdateFireDelay implements UpdateNV {
158
159        /** {@inheritDoc} */
160        @Override
161        public void setNewVal(int index) {
162            int delay = fireDelaySpinner.getIntegerValue()/TIME_STEP_SIZE;
163            // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc
164            _dataModel.setValueAt(delay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN);
165        }
166    }
167    
168    /**
169     * Update the NV controlling the enable delay
170     */
171    protected class UpdateEnableDelay implements UpdateNV {
172
173        /** {@inheritDoc} */
174        @Override
175        public void setNewVal(int index) {
176            int delay = enableDelaySpinner.getIntegerValue()/TIME_STEP_SIZE;
177            // Note that changing the data model will result in tableChanged() being called, which can manipulate the buttons, etc
178            _dataModel.setValueAt(delay, index - 1, CbusNodeNVTableDataModel.NV_SELECT_COLUMN);
179        }
180    }
181    
182//    private final static Logger log = LoggerFactory.getLogger(Sol8BaseEditNVPane.class);
183
184}