001package jmri.jmrix.can.cbus.swing.console;
002
003import java.text.DateFormat;
004import java.text.SimpleDateFormat;
005import java.util.Date;
006import javax.annotation.Nonnull;
007import javax.swing.BoxLayout;
008import javax.swing.JCheckBox;
009import jmri.jmrix.AbstractMessage;
010import jmri.jmrix.can.CanFrame;
011import jmri.jmrix.can.CanListener;
012import jmri.jmrix.can.CanMessage;
013import jmri.jmrix.can.CanReply;
014import jmri.jmrix.can.cbus.CbusEvent;
015import jmri.jmrix.can.cbus.CbusMessage;
016import jmri.jmrix.can.cbus.CbusNameService;
017import jmri.jmrix.can.cbus.CbusOpCodes;
018
019/**
020 * Panel for CBUS Console Options.
021 * <p>
022 * Contains main CBUS CAN Frame String translation options.
023 *
024 * @author Andrew Crosland Copyright (C) 2008
025 * @author Steve Young Copyright (C) 2018
026 */
027public class CbusConsoleDecodeOptionsPane extends javax.swing.JPanel implements CanListener {
028    
029    private final CbusConsolePane _mainPane;
030    private final CbusNameService nameService;
031    private final jmri.UserPreferencesManager p;
032    
033    private JCheckBox timeCheckBox;
034    private JCheckBox priCheckBox;
035    private JCheckBox canidCheckBox;
036    private JCheckBox showarrowsCheckBox;
037    private JCheckBox showRtrCheckBox;
038    private JCheckBox showOpcNameCheckBox;
039    private JCheckBox showOpcCheckBox;
040    private JCheckBox showOpcExtraCheckBox;
041    private JCheckBox showAddressCheckBox;
042    private JCheckBox showCanCheckBox;
043    private JCheckBox showEvNdName;
044    private JCheckBox showJmriBeans;
045    
046    private final DateFormat df;
047    
048    private static final String SHOWARROWS_CB = ".ShowarrowsCheckBox";
049    private static final String TIME_CB = ".TimeCheckBox";
050    private static final String SHOWOPC_CB = ".ShowOpcCheckBox";
051    private static final String SHOWEVNDNAME_CB = ".ShowEvNdName";
052    private static final String SHOWJMRIBEANS_CB = ".ShowJmriBeans";
053    private static final String SHOWOPCNAME_CB = ".ShowOpcNameCheckBox";
054    private static final String SHOWOPCEXTRA_CB = ".ShowOpcExtraCheckBox";
055    private static final String SHOWADDR_CB = ".ShowAddressCheckBox";
056    private static final String PRI_CB = ".PriCheckBox";
057    private static final String CANID_CB = ".CanidCheckBox";
058    private static final String SHOWCAN_CB = ".ShowCanCheckBox";
059    private static final String SHOWRTR_CB = ".ShowRtrCheckBox";
060    
061    public CbusConsoleDecodeOptionsPane(CbusConsolePane mainPane){
062        super();
063        _mainPane = mainPane;
064        p = jmri.InstanceManager.getDefault(jmri.UserPreferencesManager.class);
065        makePane();
066        df = new SimpleDateFormat("HH:mm:ss.SSS");
067        _mainPane.tc.addCanConsoleListener(CbusConsoleDecodeOptionsPane.this);
068        
069        nameService = new CbusNameService(_mainPane.getMemo());
070    }
071
072    private void makePane(){
073    
074        makeCheckBoxes();
075        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
076    
077        add(showarrowsCheckBox);
078        add(timeCheckBox);
079        add(showOpcCheckBox);
080        add(showEvNdName);
081        add(showJmriBeans);
082        add(showOpcNameCheckBox);
083        add(showOpcExtraCheckBox);
084        add(showAddressCheckBox);
085        add(priCheckBox);
086        add(canidCheckBox);
087        add(showCanCheckBox);
088        add(showRtrCheckBox);
089    }
090    
091    private void makeCheckBoxes() {
092    
093        timeCheckBox = new JCheckBox(Bundle.getMessage("ButtonShowTimestamp"));
094        priCheckBox = new JCheckBox(Bundle.getMessage("ButtonShowPriorities"));
095        canidCheckBox = new JCheckBox(Bundle.getMessage("CanID"));
096        showarrowsCheckBox = new JCheckBox(Bundle.getMessage("TrafficDirection"));
097        showRtrCheckBox = new JCheckBox(Bundle.getMessage("RtrCheckbox"));
098        showOpcCheckBox = new JCheckBox(Bundle.getMessage("showOpcCheckbox"));
099        showOpcNameCheckBox = new JCheckBox(Bundle.getMessage("OpcName"));
100        showOpcExtraCheckBox = new JCheckBox(Bundle.getMessage("OpcExtraCheckbox"));
101        showAddressCheckBox = new JCheckBox(Bundle.getMessage("showAddressCheckBox"));
102        showCanCheckBox = new JCheckBox(Bundle.getMessage("showCanCheckBox"));
103        showJmriBeans = new JCheckBox("JMRI");
104        showEvNdName = new JCheckBox(Bundle.getMessage("MenuItemCBUS"));
105        
106        initButtonTips();
107        
108    }
109    
110    private void initButtonTips() {
111        timeCheckBox.setToolTipText(Bundle.getMessage("TooltipShowTimestamps"));
112        priCheckBox.setToolTipText(Bundle.getMessage("TooltipShowPrios"));
113        // canidCheckBox.setToolTipText(Bundle.getMessage("CanID"));
114        showarrowsCheckBox.setToolTipText(Bundle.getMessage("TrafficDirectionTip"));
115        showRtrCheckBox.setToolTipText(Bundle.getMessage("RtrCheckboxTip"));
116        // showOpcNameCheckBox.setToolTipText(Bundle.getMessage("CanID"));
117        showOpcCheckBox.setToolTipText(Bundle.getMessage("showOpcCheckboxTip"));
118        showOpcExtraCheckBox.setToolTipText(Bundle.getMessage("OpcExtraCheckboxTip"));
119        showAddressCheckBox.setToolTipText(Bundle.getMessage("showAddressCheckBoxTip"));
120        showCanCheckBox.setToolTipText(Bundle.getMessage("showCanCheckBoxTip"));
121        showJmriBeans.setToolTipText(("<html>Display names from JMRI Turnout, Sensor and Light Table.<br>CBUS Event Table must be Running</html>"));
122        showEvNdName.setToolTipText(("<html>Display names from CBUS Event Table and CBUS Node Manager<br>CBUS Event Table and CBUS Node Manager must be started.</html>"));
123        
124        setCheckBoxes();
125    }
126    
127    private void setCheckBoxes() {
128        
129        if ( p.getSimplePreferenceState(this.getClass().getName() + ".FirstRun") ) { // NOI18N
130            showarrowsCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWARROWS_CB));
131            timeCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + TIME_CB));
132            showOpcCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWOPC_CB));
133            showEvNdName.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWEVNDNAME_CB));
134            showJmriBeans.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWJMRIBEANS_CB));
135            showOpcNameCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWOPCNAME_CB));
136            showOpcExtraCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWOPCEXTRA_CB));
137            showAddressCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWADDR_CB));
138            priCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + PRI_CB));
139            canidCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + CANID_CB));
140            showCanCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWCAN_CB));
141            showRtrCheckBox.setSelected(p.getSimplePreferenceState(getClass().getName() + SHOWRTR_CB));
142            
143        } else {
144            // set virgin load view
145            showarrowsCheckBox.setSelected(true);
146            showOpcCheckBox.setSelected(true);
147            showJmriBeans.setSelected(true);
148            showEvNdName.setSelected(true);
149            showOpcNameCheckBox.setSelected(true);
150        }
151    }
152    
153    /**
154     * Add standard logging text and send to Console.
155     * @param m CanReply or CanMessage
156     * @throws IllegalArgumentException if not a CanFrame instance
157     */
158    public void addBiDirectionalInfo(AbstractMessage m) {
159        if (!(m instanceof CanFrame)){
160            throw new IllegalArgumentException(m + " is Not a CanFrame");
161        }
162
163        CanFrame msg = (CanFrame) m;
164        updateMainStats( msg );
165        
166        StringBuilder output = new StringBuilder();
167        
168        appendIfChecked(showarrowsCheckBox, output, Bundle.getMessage((m instanceof CanMessage) ? "CBUS_OUT" : "CBUS_IN"));
169        appendIfChecked(timeCheckBox, output, df.format(new Date()));
170        
171        if (!msg.isExtended() ) {
172            appendIfChecked(showOpcCheckBox,output,CbusOpCodes.decodeopc(m));
173        }
174        
175        if (msg.isExtended() || showEvNdName.isSelected() ) {
176            output.append(CbusOpCodes.decode(m)).append(" ");
177        }
178        
179        appendJmriBeans(output, m);
180        
181        processBiDiPt2(output, m, msg);
182        
183    }
184    
185    private void processBiDiPt2(@Nonnull StringBuilder output, 
186        @Nonnull AbstractMessage m, @Nonnull CanFrame msg){
187    
188    if (CbusOpCodes.isKnownOpc(m) ) {
189            appendIfChecked(showOpcNameCheckBox,output,Bundle.getMessage("CBUS_" + CbusOpCodes.decodeopc(m)));
190            appendIfChecked(showOpcExtraCheckBox,output,Bundle.getMessage("CTIP_" + CbusOpCodes.decodeopc(m)));
191        }
192        
193        appendIfChecked(showAddressCheckBox,output,Bundle.getMessage("addressGrouping",CbusMessage.toAddress(m))); 
194
195        addPriority(m,msg,output);
196        appendIfChecked(canidCheckBox,output,Bundle.getMessage("CanIDLabel",CbusMessage.getId(m)));                
197        appendIfChecked(showCanCheckBox,output,msg.toString());
198        appendIfChecked(showRtrCheckBox, output, Bundle.getMessage( msg.isRtr() ? "IsRtrFrame" : "IsNotRtrFrame"));
199
200        // complete line and send to console
201        output.append("\n");
202        _mainPane.nextLine( (
203            (m instanceof CanMessage) ? Bundle.getMessage("EventSent"): Bundle.getMessage("EventReceived") )
204            + ": " + m.toMonitorString() + "\n", output.toString(),
205            (_mainPane.displayPane.highlightFrame != null) ? _mainPane.displayPane.highlightFrame.highlight(m) : -1);
206        
207    }
208    
209    private void updateMainStats(CanFrame msg) {
210        _mainPane.statsPane.incremenetTotal();
211        if (CbusMessage.isEvent((AbstractMessage)msg)) {
212            _mainPane.statsPane.incrementEvents();
213        }
214        if (!msg.isExtended() && CbusOpCodes.isDcc(CbusMessage.getOpcode((AbstractMessage)msg))) {
215            _mainPane.statsPane.incrementDcc();
216        }
217    }
218    
219    private void addPriority( AbstractMessage m, CanFrame cfm, StringBuilder output ){
220        if (priCheckBox.isSelected() && !cfm.isExtended()) {
221            output.append(Bundle.getMessage("DynPriTitle")).append(": ")
222                .append(CbusMessage.getPri(m) / 4).append(" ")
223                .append(Bundle.getMessage("MinPriTitle")).append(": ")
224                .append(CbusMessage.getPri(m) & 3).append(" ");
225        }
226    }
227    
228    private void appendJmriBeans(StringBuilder output, AbstractMessage m){
229    
230        if ( showJmriBeans.isSelected() && CbusMessage.isEvent(m)) {
231            
232            int en = CbusMessage.getEvent(m);
233            int nn = CbusMessage.getNodeNumber(m);
234            
235            if (!showEvNdName.isSelected()) {
236                output.append(new CbusEvent(nn,en));
237            }
238            output.append(nameService.getJmriBeans(nn, en, CbusEvent.getEvState(m))).append(" ");
239        }
240    }
241    
242    private void appendIfChecked( JCheckBox box, StringBuilder output, String toAdd){
243        if (box.isSelected()) {
244           output.append(toAdd).append(" ");
245        }
246    }
247    
248    /**
249     * {@inheritDoc}
250     */
251    @Override
252    public void message(CanMessage m) {  // process an outgoing message and log it
253        if ( ( _mainPane.displayPane.filterFrame!=null ) && ( _mainPane.displayPane.filterFrame.filter(m)) ) {
254            return;
255        }
256        _mainPane.statsPane.incremenetSent();
257        
258        addBiDirectionalInfo(m);
259                
260    }
261
262    /**
263     * {@inheritDoc}
264     */
265    @Override
266    public void reply(CanReply r) {  // receive a reply message and log it
267        if ( ( _mainPane.displayPane.filterFrame!=null ) && ( _mainPane.displayPane.filterFrame.filter(r) ) ) {
268            return;
269        }
270        _mainPane.statsPane.incremenetReceived();
271        _mainPane.packetPane.setLastReceived(r);
272        
273        addBiDirectionalInfo(r);
274        
275    }
276    
277    public void dispose(){
278        removeTc(_mainPane.tc);
279        p.setSimplePreferenceState(getClass().getName() + ".FirstRun", true); // NOI18N
280        p.setSimplePreferenceState(getClass().getName() + SHOWARROWS_CB, showarrowsCheckBox.isSelected());
281        p.setSimplePreferenceState(getClass().getName() + TIME_CB, timeCheckBox.isSelected());
282        p.setSimplePreferenceState(getClass().getName() + SHOWOPC_CB, showOpcCheckBox.isSelected());
283        p.setSimplePreferenceState(getClass().getName() + SHOWEVNDNAME_CB, showEvNdName.isSelected());
284        p.setSimplePreferenceState(getClass().getName() + SHOWJMRIBEANS_CB, showJmriBeans.isSelected());
285        p.setSimplePreferenceState(getClass().getName() + SHOWOPCNAME_CB, showOpcNameCheckBox.isSelected());
286        p.setSimplePreferenceState(getClass().getName() + SHOWOPCEXTRA_CB, showOpcExtraCheckBox.isSelected());
287        p.setSimplePreferenceState(getClass().getName() + SHOWADDR_CB, showAddressCheckBox.isSelected());
288        p.setSimplePreferenceState(getClass().getName() + PRI_CB, priCheckBox.isSelected());
289        p.setSimplePreferenceState(getClass().getName() + CANID_CB, canidCheckBox.isSelected());
290        p.setSimplePreferenceState(getClass().getName() + SHOWCAN_CB, showCanCheckBox.isSelected());
291        p.setSimplePreferenceState(getClass().getName() + SHOWRTR_CB, showRtrCheckBox.isSelected());
292    }
293    
294    // private final static org.slf4j.Logger log = LoggerFactory.getLogger(CbusConsoleDecodeOptionsPane.class);
295}