001package jmri.jmrix.can.cbus.swing.configtool; 002 003import java.awt.Color; 004import java.awt.Frame; 005import java.awt.GridBagConstraints; 006import java.awt.GridBagLayout; 007import java.awt.event.ActionEvent; 008import java.awt.event.FocusEvent; 009import java.awt.event.FocusListener; 010import javax.swing.*; 011 012import jmri.jmrix.AbstractMessage; 013import jmri.jmrix.can.CanFrame; 014import jmri.jmrix.can.CanListener; 015import jmri.jmrix.can.CanSystemConnectionMemo; 016import jmri.jmrix.can.cbus.CbusMessage; 017import jmri.jmrix.can.cbus.swing.console.CbusConsolePane; 018import jmri.jmrix.can.cbus.swing.CbusEventHighlightFrame; 019import jmri.jmrix.can.cbus.swing.CbusFilterFrame; 020import jmri.util.swing.JmriJOptionPane; 021 022/** 023 * Pane for user creation of Sensor, Turnouts and Lights that are linked to CBUS 024 * events. 025 * 026 * @author Bob Jacobsen Copyright (C) 2008 027 * @since 2.3.1 028 */ 029public class ConfigToolPane extends jmri.jmrix.can.swing.CanPanel implements CanListener { 030 031 static int configtool_instance_num; 032 final static int NRECORDERS = 6; 033 private final CbusEventRecorder[] recorders = new CbusEventRecorder[NRECORDERS]; 034 private CbusFilterFrame _filterFrame; 035 private CbusEventHighlightFrame _highlightFrame; 036 private final CbusConsolePane _console; 037 protected JButton filterButton; 038 protected JButton highlightButton; 039 private JButton resetCaptureButton; 040 041 public static void incrementInstance() { 042 configtool_instance_num++; 043 } 044 045 public static int getConfigToolInstanceNum() { 046 log.debug("instance num {}",configtool_instance_num); 047 return configtool_instance_num; 048 } 049 050 public ConfigToolPane() { 051 super(); 052 _filterFrame = null; 053 _highlightFrame = null; 054 _console = null; 055 } 056 057 public ConfigToolPane(CbusConsolePane console, CbusFilterFrame filterFrame, CbusEventHighlightFrame highlightFrame) { 058 super(); 059 _filterFrame = filterFrame; 060 _highlightFrame = highlightFrame; 061 _console = console; 062 } 063 064 public void init() { 065 // log.debug("ConfigToolPane init"); 066 067 this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 068 069 // add event displays 070 JPanel p1 = new JPanel(); 071 p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS)); 072 073 JPanel buttons = new JPanel(); 074 buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS)); 075 076 filterButton = new JButton(Bundle.getMessage("ButtonFilter")); 077 filterButton.setVisible(true); 078 filterButton.setToolTipText(Bundle.getMessage("TooltipFilter")); 079 buttons.add(filterButton); 080 081 filterButton.addActionListener(this::filterButtonActionPerformed); 082 083 084 highlightButton = new JButton(Bundle.getMessage("ButtonHighlight")); 085 highlightButton.setVisible(true); 086 highlightButton.setToolTipText(Bundle.getMessage("TooltipHighlighter")); 087 buttons.add(highlightButton); 088 089 highlightButton.addActionListener(this::highlightButtonActionPerformed); 090 091 resetCaptureButton = new JButton(Bundle.getMessage("ButtonResetCapture")); 092 resetCaptureButton.setVisible(true); 093 resetCaptureButton.setHorizontalAlignment(SwingConstants.RIGHT); 094 buttons.add(resetCaptureButton); 095 096 resetCaptureButton.addActionListener(this::resetCaptureButtonActionPerformed); 097 098 p1.add(buttons); 099 100 for (int i = 0; i < recorders.length; i++) { 101 recorders[i] = new CbusEventRecorder(); 102 p1.add(recorders[i]); 103 } 104 p1.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutEvents"))); 105 add(p1); 106 107 // add sensor 108 makeSensor = new MakeNamedBean("LabelEventActive", "LabelEventInactive") { 109 @Override 110 void create(String name) { 111 try { 112 memo.get(jmri.SensorManager.class).provideSensor(name); 113 } 114 catch (IllegalArgumentException ex) { 115 JmriJOptionPane.showMessageDialog(this, 116 ex.getMessage(), Bundle.getMessage("WarningTitle"), 117 JmriJOptionPane.ERROR_MESSAGE); 118 } 119 } 120 }; 121 makeSensor.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TitleAddX", Bundle.getMessage("BeanNameSensor")))); 122 add(makeSensor); 123 124 // add turnout 125 makeTurnout = new MakeNamedBean("LabelEventThrown", "LabelEventClosed") { 126 @Override 127 void create(String name) { 128 try { 129 memo.get(jmri.TurnoutManager.class).provideTurnout(name); 130 } 131 catch (IllegalArgumentException ex) { 132 JmriJOptionPane.showMessageDialog(this, 133 ex.getMessage(), Bundle.getMessage("WarningTitle"), 134 JmriJOptionPane.ERROR_MESSAGE); 135 } 136 } 137 }; 138 makeTurnout.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TitleAddX", Bundle.getMessage("BeanNameTurnout")))); 139 add(makeTurnout); 140 141 // add light 142 makeLight = new MakeNamedBean("LabelEventLightOn", "LabelEventLightOff") { 143 @Override 144 void create(String name) { 145 try { 146 memo.get(jmri.LightManager.class).provideLight(name); 147 } 148 catch (Exception ex) { 149 JmriJOptionPane.showMessageDialog(this, 150 ex.getMessage(), Bundle.getMessage("WarningTitle"), 151 JmriJOptionPane.ERROR_MESSAGE); 152 } 153 } 154 }; 155 makeLight.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TitleAddX", Bundle.getMessage("BeanNameLight")))); 156 add(makeLight); 157 158 } 159 160 @Override 161 public void initComponents(CanSystemConnectionMemo memo) { 162 super.initComponents(memo); 163 addTc(memo); 164 incrementInstance(); 165 init(); 166 } 167 168 @Override 169 public String getTitle() { 170 if (memo != null) { 171 StringBuilder title = new StringBuilder(20); 172 title.append(memo.getUserName()); 173 title.append(" "); 174 title.append(Bundle.getMessage("CapConfigTitle")); 175 if (getConfigToolInstanceNum() > 1) { 176 title.append(" "); 177 title.append( getConfigToolInstanceNum() ); 178 } 179 return title.toString(); 180 } 181 return Bundle.getMessage("CapConfigTitle"); 182 } 183 184 private MakeNamedBean makeSensor; 185 private MakeNamedBean makeTurnout; 186 private MakeNamedBean makeLight; 187 188 @Override 189 public void reply(jmri.jmrix.can.CanReply m) { 190 sendToListeners(m); 191 } 192 193 /** {@inheritDoc} */ 194 @Override 195 public void message(jmri.jmrix.can.CanMessage m) { 196 sendToListeners(m); 197 } 198 199 private void sendToListeners( AbstractMessage m ){ 200 if ( ((CanFrame)m).extendedOrRtr()) { 201 return; 202 } 203 if ( ( _filterFrame!=null ) && ( _filterFrame.filter(m)) ) { 204 return; 205 } 206 // forward to anybody waiting to capture 207 makeSensor.processFrame(m); 208 makeTurnout.processFrame(m); 209 makeLight.processFrame(m); 210 for (CbusEventRecorder recorder : recorders) { 211 if (recorder.waiting()) { 212 recorder.processFrame(m); 213 break; 214 } 215 } 216 } 217 218 /** {@inheritDoc} */ 219 @Override 220 public String getHelpTarget() { 221 return "package.jmri.jmrix.can.cbus.swing.configtool.ConfigToolFrame"; 222 } 223 224 @Override 225 public void dispose() { 226 removeTc(memo); 227 clearFilterFrame(); 228 clearHighlightFrame(); 229 super.dispose(); 230 } 231 232 private void clearFilterFrame(){ 233 if (_filterFrame != null) { 234 _filterFrame.dispose(); 235 } 236 _filterFrame=null; 237 } 238 239 private void clearHighlightFrame(){ 240 if (_highlightFrame != null) { 241 _highlightFrame.dispose(); 242 } 243 _highlightFrame=null; 244 } 245 246 247 public void resetCaptureButtonActionPerformed(ActionEvent e) { 248 for (CbusEventRecorder recorder : recorders) { 249 recorder.capture.setSelected(true); 250 } 251 } 252 253 public void filterButtonActionPerformed(ActionEvent e) { 254 // log.debug("Cbus Console filter button action performed"); 255 256 if ( _console != null ) { 257 _console.displayPane.filterButton.doClick(); 258 return; 259 } 260 261 if (_filterFrame == null) { 262 _filterFrame = new CbusFilterFrame(_console,this); 263 _filterFrame.initComponents(); 264 } else { 265 _filterFrame.setState(Frame.NORMAL); 266 } 267 _filterFrame.setVisible(true); 268 } 269 270 public void highlightButtonActionPerformed(ActionEvent e) { 271 // log.debug("Cbus Console filter button action performed"); 272 if ( _console != null ) { 273 _console.displayPane.highlightButton.doClick(); 274 return; 275 } 276 if (_highlightFrame == null) { 277 _highlightFrame = new CbusEventHighlightFrame(null,this); 278 _highlightFrame.initComponents(); 279 280 } else { 281 _highlightFrame.setState(Frame.NORMAL); 282 } 283 _highlightFrame.setVisible(true); 284 } 285 286 public void setHighlighter( CbusEventHighlightFrame highlightFrame){ 287 _highlightFrame = highlightFrame; 288 } 289 290 public void setFilter( CbusFilterFrame filterFrame){ 291 _filterFrame = filterFrame; 292 } 293 294 /** 295 * Class to build one NamedBean 296 */ 297 private class MakeNamedBean extends JPanel { 298 299 private JTextField f1 = new JTextField(15); 300 private JTextField f2 = new JTextField(15); 301 private JTextField f3 = new JTextField(15); 302 303 private final JButton bc; 304 305 JToggleButton b1 = new JToggleButton(Bundle.getMessage("ButtonCaptureNext")); 306 JToggleButton b2 = new JToggleButton(Bundle.getMessage("ButtonCaptureNext")); 307 JToggleButton b3 = new JToggleButton(Bundle.getMessage("ButtonCaptureNext")); 308 309 private final JToggleButton[] captureNextButtons = new JToggleButton[]{b1,b2,b3}; 310 private final JTextField[] fields = new JTextField[]{f1,f2,f3}; 311 312 /** 313 * Create CBUS NamedBean using a JPanel for user interaction. 314 * 315 * @param name1 string for Label 1 in configuration pane 316 * @param name2 string for Label 2 in configuration pane 317 */ 318 MakeNamedBean(String name1, String name2) { 319 // actions 320 bc = new JButton(Bundle.getMessage("ButtonCreate")); 321 bc.addActionListener((ActionEvent e) -> { 322 if (f2.getText().isEmpty()) { 323 create(f1.getText()); 324 } else { 325 create(f1.getText() + ";" + f2.getText()); 326 } 327 }); 328 329 initGui(name1, name2); 330 } 331 332 private void initGui(String name1, String name2){ 333 334 // GUI 335 setLayout(new GridBagLayout()); 336 GridBagConstraints c = new GridBagConstraints(); 337 c.gridwidth = 1; 338 c.gridheight = 1; 339 340 c.gridx = 0; 341 c.gridy = 0; 342 c.anchor = GridBagConstraints.EAST; 343 add(new JLabel(Bundle.getMessage(name1)), c); 344 345 c.gridx = 1; 346 c.gridy = 0; 347 c.anchor = GridBagConstraints.WEST; 348 add(f1, c); 349 350 c.gridx = 2; 351 c.gridy = 0; 352 c.anchor = GridBagConstraints.WEST; 353 add(b1, c); 354 b1.setToolTipText(Bundle.getMessage("CaptureNextTooltip")); 355 356 c.gridx = 0; 357 c.gridy = 1; 358 c.anchor = GridBagConstraints.EAST; 359 add(new JLabel(Bundle.getMessage(name2)), c); 360 361 c.gridx = 1; 362 c.gridy = 1; 363 c.anchor = GridBagConstraints.EAST; 364 add(f2, c); 365 366 c.gridx = 2; 367 c.gridy = 1; 368 c.anchor = GridBagConstraints.WEST; 369 add(b2, c); 370 b2.setToolTipText(Bundle.getMessage("CaptureNextTooltip")); 371 372 c.gridx = 1; 373 c.gridy = 2; 374 c.anchor = GridBagConstraints.WEST; 375 add(bc, c); 376 bc.setToolTipText(Bundle.getMessage("CreateTooltip")); 377 } 378 379 void create(String name) { 380 } 381 382 public void processFrame(AbstractMessage m){ 383 384 int high = (_highlightFrame != null) ? _highlightFrame.highlight(m) : -1; 385 for (int i=0; i < 3; i++){ 386 387 if (captureNextButtons[i].isSelected()) { 388 fields[i].setText(CbusMessage.toAddress(m)); 389 captureNextButtons[i].setSelected(false); 390 if ( high > -1 ) { 391 fields[i].setBackground(CbusEventHighlightFrame.highlightColors[high]); 392 } else { 393 fields[i].setBackground(Color.WHITE); 394 } 395 } 396 } 397 } 398 } 399 400 /** 401 * Class to handle recording and presenting one event. 402 */ 403 private class CbusEventRecorder extends JPanel implements FocusListener { 404 405 CbusEventRecorder() { 406 super(); 407 408 init(); 409 event.setEditable(false); 410 event.setDragEnabled(true); 411 event.setBackground(Color.WHITE); 412 capture.setSelected(true); 413 414 } 415 416 final void init() { 417 event.addFocusListener(this); 418 this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); 419 add(event); 420 add(capture); 421 } 422 423 JCheckBox capture = new JCheckBox(Bundle.getMessage("MsgCaptureNext")); 424 JTextField event = new JTextField(15); 425 426 boolean waiting() { 427 return capture.isSelected(); 428 } 429 430 public void processFrame(AbstractMessage m) { 431 if (capture.isSelected()) { 432 event.setText(CbusMessage.toAddress(m)); 433 capture.setSelected(false); 434 int high = (_highlightFrame != null) ? _highlightFrame.highlight(m) : -1; 435 if ( high > -1 ) { 436 event.setBackground(CbusEventHighlightFrame.highlightColors[high]); 437 } else { 438 event.setBackground(Color.WHITE); 439 } 440 } 441 } 442 443 @Override 444 public void focusGained(FocusEvent fe) { 445 JTextField txt = (JTextField)fe.getComponent(); 446 txt.selectAll(); 447 } 448 449 @Override 450 public void focusLost(FocusEvent e) { 451 } 452 453 } 454 455 /** 456 * Nested class to create one of these using old-style defaults. 457 */ 458 static public class Default extends jmri.jmrix.can.swing.CanNamedPaneAction { 459 public Default() { 460 super(Bundle.getMessage("CapConfigTitle"), 461 new jmri.util.swing.sdi.JmriJFrameInterface(), 462 ConfigToolPane.class.getName(), 463 jmri.InstanceManager.getDefault(CanSystemConnectionMemo.class)); 464 } 465 } 466 467 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ConfigToolPane.class); 468 469}