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