001package jmri.jmrix.openlcb.swing.lccpro; 002 003import java.awt.*; 004 005import java.beans.PropertyChangeEvent; 006import java.beans.PropertyChangeListener; 007import java.awt.event.WindowEvent; 008 009import java.io.File; 010import java.io.IOException; 011 012import javax.swing.*; 013 014import jmri.*; 015import jmri.jmrix.can.CanSystemConnectionMemo; 016import jmri.util.swing.JmriJOptionPane; 017 018import org.openlcb.*; 019import org.openlcb.cdi.impl.ConfigRepresentation; 020 021/** 022 * Do a backup of a specified node. 023 * 024 * Not truly an Action, though it might be some day 025 * @author Bob Jacobsen (c) 2026 026 */ 027 028 029class NodeBackupAction { 030 031 private ConfigRepresentation _cdi; 032 private String _name; 033 034 static JFileChooser directoryChooser = new JFileChooser(); 035 static final String PREFNAME = "backupDirectory"; 036 037 static boolean fileConfigured; 038 039 static { 040 directoryChooser.setFileSelectionMode(javax.swing.JFileChooser.DIRECTORIES_ONLY); 041 directoryChooser.setDialogTitle(Bundle.getMessage("ChooseADirectory")); 042 directoryChooser.setSelectedFile(new File(".")); 043 044 var prefsMgr = InstanceManager.getDefault(UserPreferencesManager.class); 045 var dirPref = prefsMgr.getProperty(NodeBackupAction.class.getName(), PREFNAME); 046 if (dirPref != null) { 047 directoryChooser.setSelectedFile(new File(dirPref.toString())); 048 fileConfigured = true; 049 } else { 050 fileConfigured = false; 051 } 052 053 } 054 055 public static void showOpenDialog(Component here) { 056 var response = directoryChooser.showOpenDialog(here); 057 058 if (response == JFileChooser.APPROVE_OPTION) { 059 String directory = directoryChooser.getSelectedFile().getAbsolutePath(); 060 var prefsMgr = InstanceManager.getDefault(UserPreferencesManager.class); 061 prefsMgr.setProperty(NodeBackupAction.class.getName(), PREFNAME, directory); 062 fileConfigured = true; 063 } 064 } 065 066 public void doBackup(MimicNodeStore.NodeMemo nodememo, CanSystemConnectionMemo memo, String name) { 067 068 if (!fileConfigured) { 069 showOpenDialog(null); // no Component in this case 070 } 071 072 var node = nodememo.getNodeID(); 073 _name = name; 074 log.info("Backup {} '{}' ", node.toString(), _name); 075 076 var iface = memo.get(OlcbInterface.class); 077 078 _cdi = iface.getConfigForNode(node); 079 080 // always show the status 081 JmriJOptionPane.showMessageDialogNonModal(null, 082 Bundle.getMessage("MessageCdiLoad", _name, node), 083 Bundle.getMessage("TitleCdiLoad", name), 084 JmriJOptionPane.INFORMATION_MESSAGE, 085 null); 086 087 if (_cdi.getRoot() != null) { 088 // configuration cache present, store and 089 // cancel window after short delay 090 storeCdiData(); 091 jmri.util.ThreadingUtil.runOnGUIDelayed(() -> { 092 closeStatusWindow(); 093 }, 1000); 094 095 } else { 096 // configuration cache present, wait for it 097 // to arrive 098 _cdi.addPropertyChangeListener(new CdiListener()); 099 } 100 } 101 102 // close the progress window and save the contents 103 // when the CDI has been completely read 104 private class CdiListener implements PropertyChangeListener { 105 @Override 106 public void propertyChange(PropertyChangeEvent e) { 107 String propertyName = e.getPropertyName(); 108 log.debug("CdiListener event = {}", propertyName); 109 110 if (propertyName.equals("UPDATE_CACHE_COMPLETE")) { 111 closeStatusWindow(); 112 storeCdiData(); 113 } 114 } 115 } 116 117 protected void closeStatusWindow() { 118 Window[] windows = Window.getWindows(); 119 for (Window window : windows) { 120 if (window instanceof JDialog) { 121 JDialog dialog = (JDialog) window; 122 if (Bundle.getMessage("TitleCdiLoad", _name).equals(dialog.getTitle())) { 123 dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING)); 124 } 125 } 126 } 127 } 128 129 protected void storeCdiData() { 130 log.debug("Load complete"); 131 var filename = org.openlcb.cdi.swing.CdiPanel 132 .fileNameGenerator.generateFileName(_cdi, _name); 133 String directory = directoryChooser.getSelectedFile().getAbsolutePath(); 134 String storeName = directory+File.separator+filename; 135 log.info("Storing to file {}", storeName); 136 try { 137 org.openlcb.cdi.cmd.BackupConfig.writeConfigToFile(storeName, _cdi); 138 } catch (IOException e) { 139 log.error("Error writing file! ", e); 140 } 141 142 } 143 144 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NodeBackupAction.class); 145}