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}