001/*============================================================================* 002 * WARNING This class contains automatically modified code. WARNING * 003 * * 004 * The method initComponents() and the variable declarations between the * 005 * "// Variables declaration - do not modify" and * 006 * "// End of variables declaration" comments will be overwritten if modified * 007 * by hand. Using the NetBeans IDE to edit this file is strongly recommended. * 008 * * 009 * See http://jmri.org/help/en/html/doc/Technical/NetBeansGUIEditor.shtml for * 010 * more information. * 011 *============================================================================*/ 012package jmri.profile; 013 014import java.awt.Cursor; 015import java.awt.Dialog; 016import java.awt.Dimension; 017import java.awt.Font; 018import java.awt.event.ActionEvent; 019import java.awt.event.ActionListener; 020import java.awt.event.FocusAdapter; 021import java.awt.event.FocusEvent; 022import java.awt.event.KeyAdapter; 023import java.awt.event.KeyEvent; 024import java.io.File; 025import java.io.IOException; 026import java.util.ResourceBundle; 027 028import javax.swing.GroupLayout; 029import javax.swing.JButton; 030import javax.swing.JFileChooser; 031import javax.swing.JLabel; 032import javax.swing.JSeparator; 033import javax.swing.JTextField; 034import javax.swing.LayoutStyle; 035import javax.swing.WindowConstants; 036import javax.swing.event.DocumentEvent; 037import javax.swing.event.DocumentListener; 038 039import jmri.util.FileUtil; 040import jmri.util.swing.JmriJOptionPane; 041 042/** 043 * Add a new {@link Profile} to JMRI. 044 * 045 * @author Randall Wood 046 */ 047public class AddProfileDialog extends javax.swing.JDialog { 048 049 private String profileId; 050 private boolean setNextProfile = false; 051 private Profile source = null; 052 053 public AddProfileDialog(java.awt.Frame parent, boolean modal, boolean setNextProfile) { 054 super(parent, modal); 055 this.setNextProfile = setNextProfile; 056 initComponents(); 057 } 058 059 AddProfileDialog(Dialog parent, boolean modal, boolean setNextProfile) { 060 super(parent, modal); 061 this.setNextProfile = setNextProfile; 062 initComponents(); 063 } 064 065 /** 066 * This method is called from within the constructor to initialize the form. 067 * WARNING: Do NOT modify this code. The content of this method is always 068 * regenerated by the Form Editor. 069 */ 070 // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents 071 private void initComponents() { 072 073 lblProfileNameAndLocation = new JLabel(); 074 jSeparator2 = new JSeparator(); 075 profileName = new JTextField(); 076 lblProfileName = new JLabel(); 077 lblProfileLocation = new JLabel(); 078 profileLocation = new JTextField(); 079 profileFolder = new JTextField(); 080 btnBrowse = new JButton(); 081 lblProfileFolder = new JLabel(); 082 jSeparator1 = new JSeparator(); 083 btnCancel = new JButton(); 084 btnOk = new JButton(); 085 086 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 087 ResourceBundle bundle = ResourceBundle.getBundle("jmri/profile/Bundle"); // NOI18N 088 setTitle(bundle.getString("AddProfileDialog.title")); // NOI18N 089 setMinimumSize(new Dimension(413, 239)); 090 091 lblProfileNameAndLocation.setFont(lblProfileNameAndLocation.getFont().deriveFont(lblProfileNameAndLocation.getFont().getStyle() | Font.BOLD)); 092 lblProfileNameAndLocation.setText(bundle.getString("AddProfileDialog.lblProfileNameAndLocation.text")); // NOI18N 093 094 profileName.setText(""); 095 profileName.getDocument().addDocumentListener(new DocumentListener() { 096 @Override 097 public void changedUpdate(DocumentEvent e) { 098 profileNameActionPerformed(null); 099 } 100 @Override 101 public void insertUpdate(DocumentEvent e) { 102 profileNameActionPerformed(null); 103 } 104 @Override 105 public void removeUpdate(DocumentEvent e) { 106 profileNameActionPerformed(null); 107 } 108 }); 109 profileName.addFocusListener(new FocusAdapter() { 110 @Override 111 public void focusLost(FocusEvent evt) { 112 profileNameFocusLost(evt); 113 } 114 }); 115 profileName.addActionListener(new ActionListener() { 116 @Override 117 public void actionPerformed(ActionEvent evt) { 118 profileNameActionPerformed(evt); 119 } 120 }); 121 profileName.addKeyListener(new KeyAdapter() { 122 @Override 123 public void keyTyped(KeyEvent evt) { 124 profileNameKeyTyped(evt); 125 } 126 }); 127 128 lblProfileName.setText(bundle.getString("AddProfileDialog.lblProfileName.text")); // NOI18N 129 130 lblProfileLocation.setText(bundle.getString("AddProfileDialog.lblProfileLocation.text")); // NOI18N 131 132 profileLocation.setText(ProfileManager.getDefault().getDefaultSearchPath().getPath()); 133 profileLocation.setMinimumSize(new Dimension(14, 128)); 134 profileLocation.addFocusListener(new FocusAdapter() { 135 @Override 136 public void focusLost(FocusEvent evt) { 137 profileLocationFocusLost(evt); 138 } 139 }); 140 profileLocation.addActionListener(new ActionListener() { 141 @Override 142 public void actionPerformed(ActionEvent evt) { 143 profileLocationActionPerformed(evt); 144 } 145 }); 146 profileLocation.addKeyListener(new KeyAdapter() { 147 @Override 148 public void keyTyped(KeyEvent evt) { 149 profileLocationKeyTyped(evt); 150 } 151 }); 152 153 profileFolder.setEditable(false); 154 profileFolder.setText(ProfileManager.getDefault().getDefaultSearchPath().getPath()); 155 profileFolder.setEnabled(false); 156 profileFolder.addActionListener(new ActionListener() { 157 @Override 158 public void actionPerformed(ActionEvent evt) { 159 profileFolderActionPerformed(evt); 160 } 161 }); 162 163 btnBrowse.setText(bundle.getString("AddProfileDialog.btnBrowse.text")); // NOI18N 164 btnBrowse.addActionListener(new ActionListener() { 165 @Override 166 public void actionPerformed(ActionEvent evt) { 167 btnBrowseActionPerformed(evt); 168 } 169 }); 170 171 lblProfileFolder.setText(bundle.getString("AddProfileDialog.lblProfileFolder.text")); // NOI18N 172 173 btnCancel.setText(bundle.getString("AddProfileDialog.btnCancel.text")); // NOI18N 174 btnCancel.addActionListener(new ActionListener() { 175 @Override 176 public void actionPerformed(ActionEvent evt) { 177 btnCancelActionPerformed(evt); 178 } 179 }); 180 181 btnOk.setText(bundle.getString("AddProfileDialog.btnOk.text")); // NOI18N 182 btnOk.addActionListener(new ActionListener() { 183 @Override 184 public void actionPerformed(ActionEvent evt) { 185 btnOkActionPerformed(evt); 186 } 187 }); 188 189 GroupLayout layout = new GroupLayout(getContentPane()); 190 getContentPane().setLayout(layout); 191 layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 192 .addGroup(layout.createSequentialGroup() 193 .addContainerGap() 194 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 195 .addComponent(jSeparator2) 196 .addGroup(layout.createSequentialGroup() 197 .addGap(6, 6, 6) 198 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 199 .addGroup(layout.createSequentialGroup() 200 .addComponent(lblProfileName) 201 .addGap(24, 24, 24) 202 .addComponent(profileName, GroupLayout.DEFAULT_SIZE, 185, Short.MAX_VALUE)) 203 .addGroup(layout.createSequentialGroup() 204 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 205 .addComponent(lblProfileLocation) 206 .addComponent(lblProfileFolder)) 207 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 208 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 209 .addComponent(profileFolder) 210 .addComponent(profileLocation, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) 211 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 212 .addComponent(btnBrowse)) 213 .addGroup(layout.createSequentialGroup() 214 .addComponent(lblProfileNameAndLocation) 215 .addGap(0, 0, Short.MAX_VALUE)) 216 .addComponent(jSeparator1) 217 .addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 218 .addGap(0, 0, Short.MAX_VALUE) 219 .addComponent(btnOk) 220 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 221 .addComponent(btnCancel))) 222 .addContainerGap()) 223 ); 224 layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) 225 .addGroup(layout.createSequentialGroup() 226 .addContainerGap() 227 .addComponent(lblProfileNameAndLocation) 228 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 229 .addComponent(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) 230 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 231 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 232 .addComponent(profileName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 233 .addComponent(lblProfileName)) 234 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 235 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 236 .addComponent(profileLocation, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 237 .addComponent(btnBrowse) 238 .addComponent(lblProfileLocation)) 239 .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 240 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 241 .addComponent(profileFolder, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 242 .addComponent(lblProfileFolder)) 243 .addGap(18, 18, 18) 244 .addComponent(jSeparator1, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) 245 .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) 246 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 247 .addComponent(btnCancel) 248 .addComponent(btnOk)) 249 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 250 ); 251 252 pack(); 253 }// </editor-fold>//GEN-END:initComponents 254 255 private void profileNameActionPerformed(ActionEvent evt) {//GEN-FIRST:event_profileNameActionPerformed 256 String location = this.profileLocation.getText(); 257 this.profileId = FileUtil.sanitizeFilename(this.profileName.getText()); 258 if (this.profileId.isEmpty()) { 259 this.profileFolder.setText(location); 260 } else { 261 if (!location.endsWith(File.separator)) { 262 location = location + File.separator; 263 } 264 this.profileFolder.setText(location + this.profileId + Profile.EXTENSION); 265 } 266 }//GEN-LAST:event_profileNameActionPerformed 267 268 private void btnBrowseActionPerformed(ActionEvent evt) {//GEN-FIRST:event_btnBrowseActionPerformed 269 JFileChooser chooser = new jmri.util.swing.JmriJFileChooser(this.profileLocation.getText()); 270 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 271 // TODO: Use NetBeans OpenDialog if its availble 272 if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { 273 try { 274 this.profileLocation.setText(chooser.getSelectedFile().getCanonicalPath()); 275 this.profileNameActionPerformed(evt); 276 } catch (IOException ex) { 277 log.error("Error selecting profile location", ex); 278 } 279 } 280 }//GEN-LAST:event_btnBrowseActionPerformed 281 282 private void profileFolderActionPerformed(ActionEvent evt) {//GEN-FIRST:event_profileFolderActionPerformed 283 this.profileNameActionPerformed(evt); 284 }//GEN-LAST:event_profileFolderActionPerformed 285 286 private void profileLocationActionPerformed(ActionEvent evt) {//GEN-FIRST:event_profileLocationActionPerformed 287 this.profileNameActionPerformed(evt); 288 }//GEN-LAST:event_profileLocationActionPerformed 289 290 private void btnCancelActionPerformed(ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed 291 this.dispose(); 292 }//GEN-LAST:event_btnCancelActionPerformed 293 294 private void btnOkActionPerformed(ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed 295 try { 296 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 297 Profile p = new Profile(this.profileName.getText(), this.profileId, new File(this.profileFolder.getText())); 298 ProfileManager.getDefault().addProfile(p); 299 if (this.source != null) { 300 //if (this.source.equals(ProfileManager.getDefault().getActiveProfile())) { 301 // // TODO: if source is active profile, prompt user to save source 302 // InstanceManager.getDefault(ConfigureManager.class).storePrefs(); 303 //} 304 ProfileUtils.copy(source, p); 305 } 306 if (this.setNextProfile) { 307 ProfileManager.getDefault().setNextActiveProfile(p); 308 } else { 309 ProfileManager.getDefault().setActiveProfile(p); 310 } 311 ProfileManager.getDefault().saveActiveProfile(p, ProfileManager.getDefault().isAutoStartActiveProfile()); 312 if (this.source != null) { 313 log.info("Created profile \"{}\" by copying profile \"{}\"", p.getName(), this.source.getName()); 314 } else { 315 log.info("Created new profile \"{}\"", p.getName()); 316 } 317 this.setCursor(Cursor.getDefaultCursor()); 318 this.dispose(); 319 } catch (IOException | IllegalArgumentException ex) { 320 this.setCursor(Cursor.getDefaultCursor()); 321 JmriJOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), "Error Creating Profile", JmriJOptionPane.ERROR_MESSAGE); 322 log.error("Error saving profile", ex); 323 } 324 }//GEN-LAST:event_btnOkActionPerformed 325 326 private void profileNameKeyTyped(KeyEvent evt) {//GEN-FIRST:event_profileNameKeyTyped 327 this.profileNameActionPerformed(null); 328 }//GEN-LAST:event_profileNameKeyTyped 329 330 private void profileNameFocusLost(FocusEvent evt) {//GEN-FIRST:event_profileNameFocusLost 331 this.profileNameActionPerformed(null); 332 }//GEN-LAST:event_profileNameFocusLost 333 334 private void profileLocationKeyTyped(KeyEvent evt) {//GEN-FIRST:event_profileLocationKeyTyped 335 this.profileNameActionPerformed(null); 336 }//GEN-LAST:event_profileLocationKeyTyped 337 338 private void profileLocationFocusLost(FocusEvent evt) {//GEN-FIRST:event_profileLocationFocusLost 339 this.profileNameActionPerformed(null); 340 }//GEN-LAST:event_profileLocationFocusLost 341 342 // Variables declaration - do not modify//GEN-BEGIN:variables 343 private JButton btnBrowse; 344 private JButton btnCancel; 345 private JButton btnOk; 346 private JSeparator jSeparator1; 347 private JSeparator jSeparator2; 348 private JLabel lblProfileFolder; 349 private JLabel lblProfileLocation; 350 private JLabel lblProfileName; 351 private JLabel lblProfileNameAndLocation; 352 private JTextField profileFolder; 353 private JTextField profileLocation; 354 private JTextField profileName; 355 // End of variables declaration//GEN-END:variables 356 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AddProfileDialog.class); 357 358 void setSourceProfile(Profile profile) { 359 this.source = profile; 360 this.setTitle(Bundle.getMessage("AddProfileDialog.copyTitle")); 361 } 362}