001package jmri.jmrit.roster; 002 003import java.awt.Component; 004import java.awt.event.ActionEvent; 005import javax.swing.Icon; 006import javax.swing.JComboBox; 007 008import jmri.beans.BeanUtil; 009import jmri.jmrit.roster.rostergroup.RosterGroupSelector; 010import jmri.jmrit.roster.swing.RosterEntryComboBox; 011import jmri.util.FileUtil; 012import jmri.util.swing.JmriAbstractAction; 013import jmri.util.swing.JmriJOptionPane; 014import jmri.util.swing.WindowInterface; 015 016/** 017 * Remove a locomotive from the roster. 018 * 019 * <p> 020 * In case of error, this moves the definition file to a backup. This action 021 * posts a dialog box to select the loco to be deleted, and then posts an "are 022 * you sure" dialog box before acting. 023 * 024 * @author Bob Jacobsen Copyright (C) 2001, 2002 025 * @see jmri.jmrit.XmlFile 026 */ 027public class DeleteRosterItemAction extends JmriAbstractAction { 028 029 public DeleteRosterItemAction(String s, WindowInterface wi) { 030 super(s, wi); 031 } 032 033 public DeleteRosterItemAction(String s, Icon i, WindowInterface wi) { 034 super(s, i, wi); 035 } 036 037 /** 038 * @param s Name of this action, e.g. in menus 039 * @param who Component that action is associated with, used to ensure 040 * proper position in of dialog boxes 041 */ 042 public DeleteRosterItemAction(String s, Component who) { 043 super(s); 044 _who = who; 045 } 046 Component _who; 047 048 @Override 049 public void actionPerformed(ActionEvent event) { 050 051 Roster roster = Roster.getDefault(); 052 String rosterGroup = Roster.getDefault().getDefaultRosterGroup(); 053 RosterEntry[] entries; 054 // rosterGroup may legitimately be null 055 // but getProperty returns null if the property cannot be found, so 056 // we test that the property exists before attempting to get its value 057 if (BeanUtil.hasProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP)) { 058 rosterGroup = (String) BeanUtil.getProperty(wi, RosterGroupSelector.SELECTED_ROSTER_GROUP); 059 log.debug("selectedRosterGroup was {}", rosterGroup); 060 } 061 if (BeanUtil.hasProperty(wi, "selectedRosterEntries")) { 062 entries = (RosterEntry[]) BeanUtil.getProperty(wi, "selectedRosterEntries"); 063 if (entries != null) { 064 log.debug("selectedRosterEntries found {} entries", entries.length); 065 } else { 066 log.debug("selectedRosterEntries left entries null"); 067 } 068 } else { 069 entries = selectRosterEntry(rosterGroup); 070 if (entries.length > 0 ) { 071 log.debug("selectRosterEntry(rosterGroup) found {} entries", entries.length); 072 } else { 073 log.debug("selectRosterEntry(rosterGroup) found no entries"); 074 } 075 } 076 if (entries == null || entries.length == 0) { 077 return; 078 } 079 // get parent object if there is one 080 //Component parent = null; 081 //if ( event.getSource() instanceof Component) parent = (Component)event.getSource(); 082 083 // find the file for the selected entry 084 for (RosterEntry re : entries) { 085 String filename = roster.fileFromTitle(re.titleString()); 086 String fullFilename = Roster.getDefault().getRosterFilesLocation() + filename; 087 log.debug("resolves to [{}], [{}]", filename, fullFilename); 088 089 // prompt for one last chance 090 log.debug("rosterGroup now {}", rosterGroup); 091 if (rosterGroup == null) { 092 if (!userOK(re.titleString(), filename, fullFilename)) { 093 return; 094 } 095 // delete it from roster 096 roster.removeEntry(re); 097 } else { 098 String group = Roster.getRosterGroupProperty(rosterGroup); 099 log.debug("removing {} group from entry", group); 100 re.deleteAttribute(group); 101 re.updateFile(); 102 } 103 Roster.getDefault().writeRoster(); 104 105 // backup the file & delete it 106 if (rosterGroup == null) { 107 try { 108 // ensure preferences will be found 109 FileUtil.createDirectory(Roster.getDefault().getRosterFilesLocation()); 110 111 // move original file to backup 112 LocoFile df = new LocoFile(); // need a dummy object to do this operation in next line 113 df.makeBackupFile(Roster.getDefault().getRosterFilesLocation() + filename); 114 115 } catch (Exception ex) { 116 log.error("error during locomotive file output", ex); 117 } 118 } 119 } 120 121 } 122 123 protected RosterEntry[] selectRosterEntry(String rosterGroup) { 124 RosterEntry[] entries = new RosterEntry[1]; 125 // create a dialog to select the roster entry 126 JComboBox<?> selections = new RosterEntryComboBox(rosterGroup); 127 int retval = JmriJOptionPane.showOptionDialog(_who, 128 Bundle.getMessage("CopyEntrySelectDialog"), 129 Bundle.getMessage("DeleteEntryTitle roster entry"), 130 JmriJOptionPane.DEFAULT_OPTION, 131 JmriJOptionPane.INFORMATION_MESSAGE, 132 null, 133 new Object[] {Bundle.getMessage("ButtonCancel"), Bundle.getMessage("ButtonOK"), selections}, null); 134 log.debug("Dialog value {} selected {}:{}", retval, selections.getSelectedIndex(), selections.getSelectedItem()); // NOI18N 135 if (retval != 1 ) { // array position 1 ButtonOK 136 return entries; // empty 137 } 138 entries[0] = (RosterEntry) selections.getSelectedItem(); 139 return entries; 140 } 141 142 /** 143 * Can provide some mechanism to prompt for user for one last chance to 144 * change his/her mind. 145 * 146 * @param entry Roster entry being operated on 147 * @param filename Just name of file 148 * @param fullFileName including path 149 * @return true if user says to continue 150 */ 151 boolean userOK(String entry, String filename, String fullFileName) { 152 return (JmriJOptionPane.YES_OPTION == JmriJOptionPane.showConfirmDialog(_who, 153 Bundle.getMessage("DeletePrompt", entry, fullFileName), 154 Bundle.getMessage("DeleteTitle", entry), 155 JmriJOptionPane.YES_NO_OPTION)); 156 } 157 158 // never invoked, because we overrode actionPerformed above 159 @Override 160 public jmri.util.swing.JmriPanel makePanel() { 161 throw new IllegalArgumentException("Should not be invoked"); 162 } 163 164 // initialize logging 165 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DeleteRosterItemAction.class); 166 167}