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