001package jmri.jmrit.beantable; 002 003import java.awt.Container; 004import java.awt.FlowLayout; 005import java.awt.event.ItemEvent; 006import java.beans.PropertyVetoException; 007import java.util.List; 008import java.util.Map; 009 010import javax.annotation.Nonnull; 011import javax.swing.*; 012 013import jmri.*; 014import jmri.jmrit.logixng.*; 015import jmri.jmrit.logixng.SymbolTable.InitialValueType; 016import jmri.util.JmriJFrame; 017 018 019import jmri.jmrit.logixng.tools.swing.AbstractLogixNGEditor; 020import jmri.jmrit.logixng.tools.swing.LocalVariableTableModel; 021// import jmri.jmrit.logixng.tools.swing.GlobalVariableEditor; 022 023/** 024 * Swing action to create and register a LogixNG Global Variables Table. 025 * <p> 026 * Also contains the panes to create, edit, and delete a LogixNG Global Variable. 027 * <p> 028 * Most of the text used in this GUI is in BeanTableBundle.properties, accessed 029 * via Bundle.getMessage(). 030 * <p> 031 * 032 * @author Dave Duchamp Copyright (C) 2007 (LogixTableAction) 033 * @author Pete Cressman Copyright (C) 2009, 2010, 2011 (LogixTableAction) 034 * @author Matthew Harris copyright (c) 2009 (LogixTableAction) 035 * @author Dave Sand copyright (c) 2017 (LogixTableAction) 036 * @author Daniel Bergqvist copyright (c) 2022 037 */ 038public class LogixNGGlobalVariableTableAction extends AbstractLogixNGTableAction<GlobalVariable> { 039 040 /** 041 * Create a LogixNGGlobalVariablesTableAction instance. 042 * 043 * @param s the Action title, not the title of the resulting frame. Perhaps 044 * this should be changed? 045 */ 046 public LogixNGGlobalVariableTableAction(String s) { 047 super(s); 048 } 049 050 /** 051 * Create a LogixNGTableAction instance with default title. 052 */ 053 public LogixNGGlobalVariableTableAction() { 054 this(Bundle.getMessage("TitleLogixNGGlobalVariablesTable")); 055 } 056 057 @Override 058 protected void setTitle() { 059 f.setTitle(Bundle.getMessage("TitleLogixNGGlobalVariablesTable")); 060 } 061 062 @Override 063 public String getClassDescription() { 064 return Bundle.getMessage("TitleLogixNGGlobalVariablesTable"); // NOI18N 065 } 066 067 @Override 068 protected AbstractLogixNGEditor<GlobalVariable> getEditor(BeanTableDataModel<GlobalVariable> m, String sName) { 069 return null; 070 } 071 072 @Override 073 protected boolean isEditSupported() { 074 return false; 075 } 076 077 @Override 078 protected Manager<GlobalVariable> getManager() { 079 return InstanceManager.getDefault(GlobalVariableManager.class); 080 } 081 082 @Override 083 public void setEnabled(GlobalVariable globalVariable, boolean enable) { 084 } 085 086 @Override 087 protected boolean isEnabled(GlobalVariable globalVariable) { 088 return true; 089 } 090 091 @Override 092 public void enableAll(boolean enable) { 093 } 094 095 @Override 096 protected GlobalVariable createBean(String userName) { 097 GlobalVariable globalVariable = 098 InstanceManager.getDefault(GlobalVariableManager.class) 099 .createGlobalVariable(userName); 100 return globalVariable; 101 } 102 103 @Override 104 protected GlobalVariable createBean(String systemName, String userName) { 105 GlobalVariable globalVariable = 106 InstanceManager.getDefault(GlobalVariableManager.class) 107 .createGlobalVariable(systemName, userName); 108 return globalVariable; 109 } 110 111 @Override 112 public void deleteBean(GlobalVariable globalVariable) { 113 try { 114 InstanceManager.getDefault(GlobalVariableManager.class).deleteBean(globalVariable, "DoDelete"); 115 } catch (PropertyVetoException e) { 116 //At this stage the DoDelete shouldn't fail, as we have already done a can delete, which would trigger a veto 117 log.error("{} : Could not Delete.", e.getMessage()); 118 } 119 } 120/* 121 @Override 122 protected void copyBean(@Nonnull LogixNG sourceBean, @Nonnull LogixNG targetBean) { 123 for (int i = 0; i < sourceBean.getNumConditionalNGs(); i++) { 124 copyConditionalNGToLogixNG(sourceBean.getConditionalNG(i), targetBean); 125 } 126 } 127*/ 128 @Override 129 protected boolean isCopyBeanSupported() { 130 return false; 131 } 132 133 @SuppressWarnings("unchecked") // Checked cast is not possible due to type erasure 134 @Override 135 protected String getBeanText(GlobalVariable e) { 136 var content = new StringBuilder(Bundle.getMessage("LogixNG_GlobalVar_Browse_Header", 137 e.getSystemName(), 138 e.getUserName(), 139 e.getInitialValueType())); 140 content.append(Bundle.getMessage("LogixNG_GlobalVar_Browse_Value")); 141 var value = e.getValue(); 142 143 if (value instanceof Map) { 144 var map = ((Map<? extends Object, ? extends Object>)value); 145 for (var entry : map.entrySet()) { 146 var line = String.format("%n %s -> %s", 147 entry.getKey(), 148 entry.getValue()); 149 content.append(line); 150 } 151 } else if (value instanceof List) { 152 var list = ((List<? extends Object>)value); 153 for (int i=0; i < list.size(); i++) { 154 var line = String.format("%n %s", list.get(i)); 155 content.append(line); 156 } 157 } else { 158 content.append(value); 159 } 160 return content.toString(); 161 } 162 163 @Override 164 protected String getBrowserTitle() { 165 return Bundle.getMessage("LogixNG_GlobalVar_Browse_Title"); 166 } 167 168 @Override 169 protected String getAddTitleKey() { 170 return "TitleAddLogixNGGlobalVariable"; 171 } 172 173 @Override 174 protected String getCreateButtonHintKey() { 175 return "LogixNGCreateGlobalVariableButtonHint"; 176 } 177 178 /** 179 * Create or copy bean frame. 180 * 181 * @param titleId property key to fetch as title of the frame (using Bundle) 182 * @param startMessageId part 1 of property key to fetch as user instruction on 183 * pane, either 1 or 2 is added to form the whole key 184 * @return the button JPanel 185 */ 186 @Override 187 protected JPanel makeAddFrame(String titleId, String startMessageId) { 188 addLogixNGFrame = new JmriJFrame(Bundle.getMessage(titleId)); 189// addLogixNGFrame.addHelpMenu( 190// "package.jmri.jmrit.beantable.LogixNGGlobalVariableTable", true); // NOI18N 191 addLogixNGFrame.setLocation(50, 30); 192 Container contentPane = addLogixNGFrame.getContentPane(); 193 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 194 195 JPanel p; 196 p = new JPanel(); 197 p.setLayout(new FlowLayout()); 198 p.setLayout(new java.awt.GridBagLayout()); 199 java.awt.GridBagConstraints c = new java.awt.GridBagConstraints(); 200 c.gridwidth = 1; 201 c.gridheight = 1; 202 c.gridx = 0; 203 c.gridy = 0; 204 c.anchor = java.awt.GridBagConstraints.EAST; 205 p.add(_sysNameLabel, c); 206 _sysNameLabel.setLabelFor(_systemName); 207 c.gridy = 1; 208 p.add(_userNameLabel, c); 209 _userNameLabel.setLabelFor(_addUserName); 210 c.gridx = 1; 211 c.gridy = 0; 212 c.anchor = java.awt.GridBagConstraints.WEST; 213 c.weightx = 1.0; 214 c.fill = java.awt.GridBagConstraints.HORIZONTAL; // text field will expand 215 p.add(_systemName, c); 216 c.gridy = 1; 217 p.add(_addUserName, c); 218 c.gridx = 2; 219 c.gridy = 1; 220 c.anchor = java.awt.GridBagConstraints.WEST; 221 c.weightx = 1.0; 222 c.fill = java.awt.GridBagConstraints.HORIZONTAL; // text field will expand 223 c.gridy = 0; 224 p.add(_autoSystemName, c); 225 _addUserName.setToolTipText(Bundle.getMessage("LogixNGGlobalVariableUserNameHint")); // NOI18N 226 _systemName.setToolTipText(Bundle.getMessage("LogixNGGlobalVariableSystemNameHint")); // NOI18N 227 contentPane.add(p); 228 // set up message 229 JPanel panel3 = new JPanel(); 230 panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS)); 231 JPanel panel31 = new JPanel(); 232 panel31.setLayout(new FlowLayout()); 233 JLabel message1 = new JLabel(Bundle.getMessage(startMessageId + "LogixNGMessage1")); // NOI18N 234 panel31.add(message1); 235 JPanel panel32 = new JPanel(); 236 JLabel message2 = new JLabel(Bundle.getMessage(startMessageId + "LogixNGMessage2")); // NOI18N 237 panel32.add(message2); 238 panel3.add(panel31); 239 panel3.add(panel32); 240 contentPane.add(panel3); 241 242 // set up create and cancel buttons 243 JPanel panel5 = new JPanel(); 244 panel5.setLayout(new FlowLayout()); 245 // Cancel 246 JButton cancel = new JButton(Bundle.getMessage("ButtonCancel")); // NOI18N 247 panel5.add(cancel); 248 cancel.addActionListener(this::cancelAddPressed); 249 cancel.setToolTipText(Bundle.getMessage("CancelLogixNGGlobalVariableButtonHint")); // NOI18N 250 251 addLogixNGFrame.addWindowListener(new java.awt.event.WindowAdapter() { 252 @Override 253 public void windowClosing(java.awt.event.WindowEvent e) { 254 cancelAddPressed(null); 255 } 256 }); 257 contentPane.add(panel5); 258 259 _autoSystemName.addItemListener((ItemEvent e) -> { 260 autoSystemName(); 261 }); 262 return panel5; 263 } 264 265 @Override 266 protected void getListenerRefsIncludingChildren(GlobalVariable globalVariable, java.util.List<String> list) { 267 globalVariable.getListenerRefsIncludingChildren(list); 268 } 269 270 @Override 271 protected boolean hasChildren(GlobalVariable globalVariable) { 272 return false; 273 } 274 275 /** 276 * Create the JTable DataModel, along with the changes (overrides of 277 * BeanTableDataModel) for the specific case of a LogixNG table. 278 */ 279 @Override 280 protected void createModel() { 281 m = new TableModel(); 282 } 283 284 @Override 285 public void addToFrame(@Nonnull BeanTableFrame<GlobalVariable> f) { 286 f.addToBottomBox(new JLabel(Bundle.getMessage("LogixNGGlobalVariable_InfoAboutGlobalVariables")), null); 287 } 288 289 @Override 290 public void addToFrame(@Nonnull ListedTableFrame.TabbedTableItem<GlobalVariable> tti) { 291 tti.addToBottomBox(new JLabel(Bundle.getMessage("LogixNGGlobalVariable_InfoAboutGlobalVariables"))); 292 } 293 294 295 protected class TableModel extends AbstractLogixNGTableAction<GlobalVariable>.TableModel { 296 297 // overlay the state column with the edit column 298 static private final int VARIABLE_TYPE_COL = NUMCOLUMN; 299 static private final int VARIABLE_INIT_VALUE_COL = NUMCOLUMN + 1; 300 static private final int SET_TO_INIT_VALUE_COL = VARIABLE_INIT_VALUE_COL + 1; 301 static private final int NUM_COLUMNS = SET_TO_INIT_VALUE_COL + 1; 302 303 @Override 304 protected boolean isClearUserNameAllowed() { 305 return false; 306 } 307 308 @Override 309 public int getColumnCount() { 310 return NUM_COLUMNS; 311 } 312 313 @Override 314 public String getColumnName(int col) { 315 switch (col) { 316 case VARIABLE_TYPE_COL: 317 return Bundle.getMessage("LogixNGGlobalVariableColumnHeadInitialType"); 318 case VARIABLE_INIT_VALUE_COL: 319 return Bundle.getMessage("LogixNGGlobalVariableColumnHeadInitialValue"); 320 case SET_TO_INIT_VALUE_COL: 321 return Bundle.getMessage("LogixNGGlobalVariableColumnHeadSetToInitValue"); 322 default: 323 return super.getColumnName(col); 324 } 325 } 326 327 @Override 328 public Class<?> getColumnClass(int col) { 329 switch (col) { 330 case VARIABLE_TYPE_COL: 331 return InitialValueType.class; 332 case VARIABLE_INIT_VALUE_COL: 333 return String.class; 334 case SET_TO_INIT_VALUE_COL: 335 return JButton.class; 336 default: 337 return super.getColumnClass(col); 338 } 339 } 340 341 @Override 342 public int getPreferredWidth(int col) { 343 switch (col) { 344 case VARIABLE_TYPE_COL: 345 return new JTextField(12).getPreferredSize().width; 346 case VARIABLE_INIT_VALUE_COL: 347 return new JTextField(17).getPreferredSize().width; 348 case SET_TO_INIT_VALUE_COL: 349 return new JButton(Bundle.getMessage( 350 "LogixNGGlobalVariableColumnHeadSetToInitValue")) 351 .getPreferredSize().width; 352 default: 353 return super.getPreferredWidth(col); 354 } 355 } 356 357 @Override 358 public boolean isCellEditable(int row, int col) { 359 switch (col) { 360 case VARIABLE_TYPE_COL: 361 case VARIABLE_INIT_VALUE_COL: 362 case SET_TO_INIT_VALUE_COL: 363 return true; 364 default: 365 return super.isCellEditable(row, col); 366 } 367 } 368 369 @Override 370 public Object getValueAt(int row, int col) { 371 GlobalVariable gv; 372 switch (col) { 373 case VARIABLE_TYPE_COL: 374 gv = (GlobalVariable) getValueAt(row, SYSNAMECOL); 375 if (gv == null) { return null; } // Error 376 return gv.getInitialValueType(); 377 378 case VARIABLE_INIT_VALUE_COL: 379 gv = (GlobalVariable) getValueAt(row, SYSNAMECOL); 380 if (gv == null) { return null; } // Error 381 return gv.getInitialValueData(); 382 383 case SET_TO_INIT_VALUE_COL: 384 return Bundle.getMessage( 385 "LogixNGGlobalVariableColumnHeadSetToInitValue"); 386 387 default: 388 return super.getValueAt(row, col); 389 } 390 } 391 392 @SuppressWarnings("unchecked") // Unchecked cast from Object to E 393 @Override 394 public void setValueAt(Object value, int row, int col) { 395 GlobalVariable gv; 396 switch (col) { 397 case VARIABLE_TYPE_COL: 398 gv = (GlobalVariable) getValueAt(row, SYSNAMECOL); 399 gv.setInitialValueType((InitialValueType) value); 400 break; 401 402 case VARIABLE_INIT_VALUE_COL: 403 gv = (GlobalVariable) getValueAt(row, SYSNAMECOL); 404 gv.setInitialValueData((String) value); 405 break; 406 407 case SET_TO_INIT_VALUE_COL: 408 gv = (GlobalVariable) getValueAt(row, SYSNAMECOL); 409 try { 410 gv.initialize(); 411 } catch (JmriException | RuntimeException e) { 412 JOptionPane.showMessageDialog(null, 413 e.getLocalizedMessage(), 414 Bundle.getMessage("ErrorTitle"), // NOI18N 415 JOptionPane.ERROR_MESSAGE); 416 } 417 break; 418 419 default: 420 super.setValueAt(value, row, col); 421 break; 422 } 423 } 424 425 @Override 426 public void configureTable(JTable table) { 427 table.setDefaultRenderer(InitialValueType.class, 428 new LocalVariableTableModel.TypeCellRenderer()); 429 table.setDefaultEditor(InitialValueType.class, 430 new LocalVariableTableModel.TypeCellEditor()); 431 432 super.configureTable(table); 433 } 434 } 435 436 437 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogixNGGlobalVariableTableAction.class); 438 439}