001package jmri.jmrit.beantable; 002 003import java.awt.Color; 004import java.awt.event.ActionEvent; 005import java.awt.event.ActionListener; 006 007import javax.swing.BoxLayout; 008import javax.swing.JCheckBox; 009import javax.swing.JLabel; 010import javax.swing.JSpinner; 011import javax.swing.JTextField; 012import javax.swing.SpinnerNumberModel; 013 014import jmri.InstanceManager; 015import jmri.Memory; 016import jmri.MemoryManager; 017import jmri.NamedBean; 018import jmri.UserPreferencesManager; 019import jmri.util.JmriJFrame; 020import jmri.util.swing.JmriJOptionPane; 021 022// import org.slf4j.Logger; 023// import org.slf4j.LoggerFactory; 024 025/** 026 * Swing action to create and register a MemoryTable GUI. 027 * 028 * @author Bob Jacobsen Copyright (C) 2003 029 */ 030public class MemoryTableAction extends AbstractTableAction<Memory> { 031 032 /** 033 * Create an action with a specific title. 034 * <p> 035 * Note that the argument is the Action title, not the title of the 036 * resulting frame. Perhaps this should be changed? 037 * 038 * @param actionName title of the action 039 */ 040 public MemoryTableAction(String actionName) { 041 super(actionName); 042 043 // disable ourself if there is no primary Memory manager available 044 if (InstanceManager.getNullableDefault(MemoryManager.class) == null) { 045 super.setEnabled(false); 046 } 047 048 } 049 050 public MemoryTableAction() { 051 this(Bundle.getMessage("TitleMemoryTable")); 052 } 053 054 /** 055 * Create the JTable DataModel, along with the changes for the specific case 056 * of Memory objects 057 */ 058 @Override 059 protected void createModel() { 060 m = new MemoryTableDataModel(InstanceManager.getDefault(MemoryManager.class)); 061 } 062 063 /** {@inheritDoc} */ 064 @Override 065 protected void setTitle() { 066 f.setTitle(Bundle.getMessage("TitleMemoryTable")); 067 } 068 069 /** {@inheritDoc} */ 070 @Override 071 protected String helpTarget() { 072 return "package.jmri.jmrit.beantable.MemoryTable"; 073 } 074 075 JmriJFrame addFrame = null; 076 JTextField sysNameField = new JTextField(20); 077 JTextField userNameField = new JTextField(20); 078 JLabel sysNameLabel = new JLabel(Bundle.getMessage("LabelSystemName")); 079 JLabel userNameLabel = new JLabel(Bundle.getMessage("LabelUserName")); 080 SpinnerNumberModel rangeSpinner = new SpinnerNumberModel(1, 1, 100, 1); // maximum 100 items 081 JSpinner numberToAddSpinner = new JSpinner(rangeSpinner); 082 JCheckBox rangeBox = new JCheckBox(Bundle.getMessage("AddRangeBox")); 083 JCheckBox autoSystemNameBox = new JCheckBox(Bundle.getMessage("LabelAutoSysName")); 084 JLabel statusBarLabel = new JLabel(Bundle.getMessage("AddBeanStatusEnter"), JLabel.LEADING); 085 UserPreferencesManager p; 086 087 /** {@inheritDoc} */ 088 @Override 089 protected void addPressed(ActionEvent e) { 090 p = InstanceManager.getDefault(UserPreferencesManager.class); 091 if (addFrame == null) { 092 addFrame = new JmriJFrame(Bundle.getMessage("TitleAddMemory"), false, true); 093 addFrame.addHelpMenu("package.jmri.jmrit.beantable.MemoryAddEdit", true); 094 addFrame.getContentPane().setLayout(new BoxLayout(addFrame.getContentPane(), BoxLayout.Y_AXIS)); 095 096 ActionListener okListener = (ActionEvent e1) -> { 097 okPressed(e1); 098 }; 099 ActionListener cancelListener = (ActionEvent e1) -> { 100 cancelPressed(e1); 101 }; 102 AddNewBeanPanel anbp = new AddNewBeanPanel(sysNameField, userNameField, numberToAddSpinner, rangeBox, autoSystemNameBox, "ButtonCreate", okListener, cancelListener, statusBarLabel); 103 addFrame.add(anbp); 104 addFrame.getRootPane().setDefaultButton(anbp.ok); 105 addFrame.setEscapeKeyClosesWindow(true); 106 sysNameField.setToolTipText(Bundle.getMessage("SysNameToolTip", "M")); // override tooltip with bean specific letter 107 } 108 sysNameField.setBackground(Color.white); 109 // reset status bar text 110 statusBarLabel.setText(Bundle.getMessage("AddBeanStatusEnter")); 111 statusBarLabel.setForeground(Color.gray); 112 if (p.getSimplePreferenceState(systemNameAuto)) { 113 autoSystemNameBox.setSelected(true); 114 } 115 addFrame.pack(); 116 addFrame.setVisible(true); 117 } 118 119 String systemNameAuto = this.getClass().getName() + ".AutoSystemName"; 120 121 void cancelPressed(ActionEvent e) { 122 addFrame.setVisible(false); 123 addFrame.dispose(); 124 addFrame = null; 125 } 126 127 void okPressed(ActionEvent e) { 128 129 int numberOfMemory = 1; 130 131 if (rangeBox.isSelected()) { 132 numberOfMemory = (Integer) numberToAddSpinner.getValue(); 133 } 134 135 if (numberOfMemory >= 65) { // limited by JSpinnerModel to 100 136 if (JmriJOptionPane.showConfirmDialog(addFrame, 137 Bundle.getMessage("WarnExcessBeans", Bundle.getMessage("Memories"), numberOfMemory), 138 Bundle.getMessage("WarningTitle"), 139 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 140 return; 141 } 142 } 143 144 String uName = NamedBean.normalizeUserName(userNameField.getText()); 145 if (uName == null || uName.isEmpty()) { 146 uName = null; 147 } 148 String sName = sysNameField.getText(); 149 // initial check for empty entry 150 if (sName.isEmpty() && !autoSystemNameBox.isSelected()) { 151 statusBarLabel.setText(Bundle.getMessage("WarningSysNameEmpty")); 152 statusBarLabel.setForeground(Color.red); 153 sysNameField.setBackground(Color.red); 154 return; 155 } else { 156 sysNameField.setBackground(Color.white); 157 } 158 159 // Add some entry pattern checking, before assembling sName and handing it to the memoryManager 160 String statusMessage = Bundle.getMessage("ItemCreateFeedback", Bundle.getMessage("BeanNameMemory")); 161 String errorMessage = null; 162 for (int x = 0; x < numberOfMemory; x++) { 163 if (uName != null && !uName.isEmpty() 164 && InstanceManager.getDefault(MemoryManager.class).getByUserName(uName) != null 165 && !p.getPreferenceState(getClassName(), "duplicateUserName")) { 166 InstanceManager.getDefault(UserPreferencesManager.class). 167 showErrorMessage(Bundle.getMessage("ErrorTitle"), Bundle.getMessage("ErrorDuplicateUserName", uName), getClassName(), "duplicateUserName", false, true); 168 // show in status bar 169 errorMessage = Bundle.getMessage("ErrorDuplicateUserName", uName); 170 statusBarLabel.setText(errorMessage); 171 statusBarLabel.setForeground(Color.red); 172 uName = null; // new Memory objects always receive a valid system name using the next free index, but uName names must not be in use so use none in that case 173 } 174 if (!sName.isEmpty() 175 && InstanceManager.getDefault(MemoryManager.class).getBySystemName(sName) != null 176 && !p.getPreferenceState(getClassName(), "duplicateSystemName")) { 177 InstanceManager.getDefault(UserPreferencesManager.class). 178 showErrorMessage(Bundle.getMessage("ErrorTitle"), Bundle.getMessage("ErrorDuplicateSystemName", sName), getClassName(), "duplicateSystemName", false, true); 179 // show in status bar 180 errorMessage = Bundle.getMessage("ErrorDuplicateSystemName", sName); 181 statusBarLabel.setText(errorMessage); 182 statusBarLabel.setForeground(Color.red); 183 return; // new Memory objects are always valid, but system names must not be in use so skip in that case 184 } 185 try { 186 if (autoSystemNameBox.isSelected()) { 187 InstanceManager.getDefault(MemoryManager.class).newMemory(uName); 188 } else { 189 InstanceManager.getDefault(MemoryManager.class).newMemory(sName, uName); 190 } 191 } catch (IllegalArgumentException ex) { 192 // uName input no good 193 handleCreateException(sName); 194 errorMessage = Bundle.getMessage("ErrorAddFailedCheck"); 195 statusBarLabel.setText(errorMessage); 196 statusBarLabel.setForeground(Color.red); 197 return; // without creating 198 } 199 200 // add first and last names to statusMessage uName feedback string 201 // only mention first and last of rangeBox added 202 if (x == 0 || x == numberOfMemory - 1) { 203 statusMessage = statusMessage + " " + sName + " (" + uName + ")"; 204 } 205 if (x == numberOfMemory - 2) { 206 statusMessage = statusMessage + " " + Bundle.getMessage("ItemCreateUpTo") + " "; 207 } 208 209 // bump system & uName names 210 if (!autoSystemNameBox.isSelected()) { 211 sName = nextName(sName); 212 } 213 if (uName != null) { 214 uName = nextName(uName); 215 } 216 } // end of for loop creating rangeBox of Memories 217 218 // provide feedback to uName 219 if (errorMessage == null) { 220 statusBarLabel.setText(statusMessage); 221 statusBarLabel.setForeground(Color.gray); 222 } else { 223 statusBarLabel.setText(errorMessage); 224 // statusBarLabel.setForeground(Color.red); // handled when errorMassage is set to differentiate urgency 225 } 226 227 p.setSimplePreferenceState(systemNameAuto, autoSystemNameBox.isSelected()); 228 } 229 230 void handleCreateException(String sysName) { 231 JmriJOptionPane.showMessageDialog(addFrame, 232 Bundle.getMessage("ErrorMemoryAddFailed", sysName) + "\n" + Bundle.getMessage("ErrorAddFailedCheck"), 233 Bundle.getMessage("ErrorTitle"), 234 JmriJOptionPane.ERROR_MESSAGE); 235 } 236 237 /** {@inheritDoc} */ 238 @Override 239 public String getClassDescription() { 240 return Bundle.getMessage("TitleMemoryTable"); 241 } 242 243 @Override 244 public void setMessagePreferencesDetails() { 245 InstanceManager.getDefault(jmri.UserPreferencesManager.class). 246 setPreferenceItemDetails(getClassName(), "duplicateUserName", Bundle.getMessage("HideDupUserError")); // NOI18N 247 InstanceManager.getDefault(jmri.UserPreferencesManager.class). 248 setPreferenceItemDetails(getClassName(), "duplicateSystemName", Bundle.getMessage("HideDupSysError")); // NOI18N 249 super.setMessagePreferencesDetails(); 250 } 251 252 /** {@inheritDoc} */ 253 @Override 254 protected String getClassName() { 255 return MemoryTableAction.class.getName(); 256 } 257 258 // private final static Logger log = LoggerFactory.getLogger(MemoryTableAction.class); 259 260}