001package jmri.jmrit.logixng.tools.swing;
002
003
004import java.awt.*;
005import java.awt.event.*;
006import java.io.File;
007import java.io.IOException;
008
009import javax.swing.*;
010
011import jmri.InstanceManager;
012import jmri.UserPreferencesManager;
013import jmri.jmrit.logixng.Base.PrintTreeSettings;
014import jmri.util.FileUtil;
015import jmri.util.JmriJFrame;
016import jmri.util.swing.JmriJOptionPane;
017
018/**
019 * Browse window for LogixNG
020 *
021 * @author Daniel Bergqvist Copyright 2024
022 */
023public class LogixNGBrowseWindow extends JmriJFrame {
024
025    public interface GetText {
026        public String getText(PrintTreeSettings printTreeSettings);
027    }
028
029
030    // Browser Options
031    private static final String PRINT_LINE_NUMBERS_OPTION = "jmri.jmrit.logixng.PrintLineNumbers";
032    private static final String PRINT_ERROR_HANDLING_OPTION = "jmri.jmrit.logixng.ErrorHandling";
033    private static final String PRINT_NOT_CONNECTED_OPTION = "jmri.jmrit.logixng.NotConnectedSockets";
034    private static final String PRINT_LOCAL_VARIABLES_OPTION = "jmri.jmrit.logixng.LocalVariables";
035    private static final String PRINT_SYSTEM_NAMES_OPTION = "jmri.jmrit.logixng.SystemNames";
036    private static final String PRINT_DISABLED_OPTION = "jmri.jmrit.logixng.Disabled";
037
038    private PrintTreeSettings _printTreeSettings = new PrintTreeSettings();
039    private JTextArea _textContent;
040    private JFileChooser userFileChooser =
041            new jmri.util.swing.JmriJFileChooser(FileUtil.getUserFilesPath());
042    
043
044    public LogixNGBrowseWindow(String title) {
045        super(title, false, true);
046    }
047    
048    public void getPrintTreeSettings() {
049        // Set options
050        InstanceManager.getOptionalDefault(UserPreferencesManager.class).ifPresent((prefMgr) -> {
051            _printTreeSettings._printLineNumbers = prefMgr.getSimplePreferenceState(PRINT_LINE_NUMBERS_OPTION);
052            _printTreeSettings._printErrorHandling = prefMgr.getSimplePreferenceState(PRINT_ERROR_HANDLING_OPTION);
053            _printTreeSettings._printNotConnectedSockets = prefMgr.getSimplePreferenceState(PRINT_NOT_CONNECTED_OPTION);
054            _printTreeSettings._printLocalVariables = prefMgr.getSimplePreferenceState(PRINT_LOCAL_VARIABLES_OPTION);
055            _printTreeSettings._printSystemNames = prefMgr.getSimplePreferenceState(PRINT_SYSTEM_NAMES_OPTION);
056            _printTreeSettings._printDisabled = prefMgr.getSimplePreferenceState(PRINT_DISABLED_OPTION);
057            _printTreeSettings._printStartup = true;
058        });
059    }
060
061     /**
062     * Update text in the browser window.
063     * @param getText the text
064     */
065    public void updateBrowserText(GetText getText) {
066        if (_textContent != null) {
067            _textContent.setText(getText.getText(_printTreeSettings));
068        }
069    }
070
071    /**
072     * Create and initialize the browser window.
073     * @param browseMonoSpace use monospace font?
074     * @param showSettingsPanel show settings panel?
075     * @param header the header
076     * @param systemName the system name of the bean or the header
077     * @param getText the text
078     */
079    public void makeBrowserWindow(
080            boolean browseMonoSpace, boolean showSettingsPanel,
081            String header, String systemName, GetText getText) {
082
083        addWindowListener(new WindowAdapter() {
084            @Override
085            public void windowClosed(WindowEvent e) {
086                _textContent = null;
087            }
088        });
089
090        Container contentPane = getContentPane();
091        contentPane.setLayout(new BorderLayout());
092
093        // bean header information
094        JPanel topPanel = new JPanel();
095        topPanel.add(new JLabel(header));
096        contentPane.add(topPanel, BorderLayout.NORTH);
097
098        // Build the conditionalNGs listing
099        _textContent = new JTextArea(getText.getText(_printTreeSettings));
100
101        if (browseMonoSpace) {
102            _textContent.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
103        }
104        JScrollPane scrollPane = new JScrollPane(_textContent);
105        contentPane.add(scrollPane);
106
107        JPanel bottomPanel = new JPanel();
108        bottomPanel.setLayout(new BorderLayout());
109        JButton helpBrowse = new JButton(Bundle.getMessage("MenuHelp"));   // NOI18N
110        bottomPanel.add(helpBrowse, BorderLayout.WEST);
111        helpBrowse.addActionListener((ActionEvent e) -> {
112            JmriJOptionPane.showMessageDialog(this,
113                    Bundle.getMessage("LogixNG_Browse_HelpText"),   // NOI18N
114                    Bundle.getMessage("BrowserHelpTitle"),  // NOI18N
115                    JmriJOptionPane.INFORMATION_MESSAGE);
116        });
117
118        if (showSettingsPanel) {
119            JPanel settingsPanel = getSettingsPanel(getText);
120            bottomPanel.add(settingsPanel, BorderLayout.CENTER);
121        }
122        JButton saveBrowse = new JButton(Bundle.getMessage("BrowserSaveButton"));   // NOI18N
123        saveBrowse.setToolTipText(Bundle.getMessage("BrowserSaveButtonHint"));      // NOI18N
124        bottomPanel.add(saveBrowse, BorderLayout.EAST);
125        saveBrowse.addActionListener((ActionEvent e) -> {
126            saveBrowserPressed(header, systemName);
127        });
128        contentPane.add(bottomPanel, BorderLayout.SOUTH);
129
130        pack();
131        setVisible(true);
132    }  // makeBrowserWindow
133
134    /**
135     * Save the bean browser window content to a text file.
136     * @param header the header
137     * @param systemName the system name of the bean or the header
138     */
139    void saveBrowserPressed(String header, String systemName) {
140        userFileChooser.setApproveButtonText(Bundle.getMessage("BrowserSaveDialogApprove"));  // NOI18N
141        userFileChooser.setDialogTitle(Bundle.getMessage("BrowserSaveDialogTitle"));  // NOI18N
142        userFileChooser.rescanCurrentDirectory();
143        // Default to logixNG system name.txt
144        String suggestedFileName = systemName.replace(':', '_') + ".txt";
145        userFileChooser.setSelectedFile(new File(suggestedFileName));  // NOI18N
146        int retVal = userFileChooser.showSaveDialog(null);
147        if (retVal != JFileChooser.APPROVE_OPTION) {
148            log.debug("Save browser content stopped, no file selected");  // NOI18N
149            return;  // give up if no file selected or cancel pressed
150        }
151        File file = userFileChooser.getSelectedFile();
152        log.debug("Save browser content to '{}'", file);  // NOI18N
153
154        if (file.exists()) {
155            Object[] options = {Bundle.getMessage("BrowserSaveDuplicateReplace"),  // NOI18N
156                    Bundle.getMessage("BrowserSaveDuplicateAppend"),  // NOI18N
157                    Bundle.getMessage("ButtonCancel")};               // NOI18N
158            int selectedOption = JmriJOptionPane.showOptionDialog(null,
159                    Bundle.getMessage("BrowserSaveDuplicatePrompt", file.getName()), // NOI18N
160                    Bundle.getMessage("BrowserSaveDuplicateTitle"),   // NOI18N
161                    JmriJOptionPane.DEFAULT_OPTION,
162                    JmriJOptionPane.WARNING_MESSAGE,
163                    null, options, options[0]);
164            if (selectedOption == 2 || selectedOption == -1) {
165                log.debug("Save browser content stopped, file replace/append cancelled");  // NOI18N
166                return;  // Cancel selected or dialog box closed
167            }
168            if (selectedOption == 0) {
169                FileUtil.delete(file);  // Replace selected
170            }
171        }
172
173        // Create the file content
174        try {
175            // Add bean Header inforation first
176            FileUtil.appendTextToFile(file, header);
177            FileUtil.appendTextToFile(file, "-".repeat(header.length()));
178            FileUtil.appendTextToFile(file, "");
179            FileUtil.appendTextToFile(file, _textContent.getText());
180        } catch (IOException e) {
181            log.error("Unable to write browser content to '{}'", file, e);  // NOI18N
182        }
183    }
184
185    protected JPanel getSettingsPanel(GetText getText) {
186        JPanel checkBoxPanel = new JPanel();
187
188        JCheckBox printLineNumbers = new JCheckBox(Bundle.getMessage("LogixNG_Browse_PrintLineNumbers"));
189        printLineNumbers.setSelected(_printTreeSettings._printLineNumbers);
190        printLineNumbers.addChangeListener((event) -> {
191            if (_printTreeSettings._printLineNumbers != printLineNumbers.isSelected()) {
192                _printTreeSettings._printLineNumbers = printLineNumbers.isSelected();
193                InstanceManager.getOptionalDefault(UserPreferencesManager.class).ifPresent((prefMgr) -> {
194                    prefMgr.setSimplePreferenceState(PRINT_LINE_NUMBERS_OPTION, printLineNumbers.isSelected());
195                });
196                updateBrowserText(getText);
197            }
198        });
199
200        JCheckBox printErrorHandling = new JCheckBox(Bundle.getMessage("LogixNG_Browse_PrintErrorHandling"));
201        printErrorHandling.setSelected(_printTreeSettings._printErrorHandling);
202        printErrorHandling.addChangeListener((event) -> {
203            if (_printTreeSettings._printErrorHandling != printErrorHandling.isSelected()) {
204                _printTreeSettings._printErrorHandling = printErrorHandling.isSelected();
205                InstanceManager.getOptionalDefault(UserPreferencesManager.class).ifPresent((prefMgr) -> {
206                    prefMgr.setSimplePreferenceState(PRINT_ERROR_HANDLING_OPTION, printErrorHandling.isSelected());
207                });
208                updateBrowserText(getText);
209            }
210        });
211
212        JCheckBox printNotConnectedSockets = new JCheckBox(Bundle.getMessage("LogixNG_Browse_PrintNotConnectedSocket"));
213        printNotConnectedSockets.setSelected(_printTreeSettings._printNotConnectedSockets);
214        printNotConnectedSockets.addChangeListener((event) -> {
215            if (_printTreeSettings._printNotConnectedSockets != printNotConnectedSockets.isSelected()) {
216                _printTreeSettings._printNotConnectedSockets = printNotConnectedSockets.isSelected();
217                updateBrowserText(getText);
218                InstanceManager.getOptionalDefault(jmri.UserPreferencesManager.class).ifPresent((prefMgr) -> {
219                    prefMgr.setSimplePreferenceState(PRINT_NOT_CONNECTED_OPTION, printNotConnectedSockets.isSelected());
220                });
221            }
222        });
223
224        JCheckBox printLocalVariables = new JCheckBox(Bundle.getMessage("LogixNG_Browse_PrintLocalVariables"));
225        printLocalVariables.setSelected(_printTreeSettings._printLocalVariables);
226        printLocalVariables.addChangeListener((event) -> {
227            if (_printTreeSettings._printLocalVariables != printLocalVariables.isSelected()) {
228                _printTreeSettings._printLocalVariables = printLocalVariables.isSelected();
229                updateBrowserText(getText);
230                InstanceManager.getOptionalDefault(jmri.UserPreferencesManager.class).ifPresent((prefMgr) -> {
231                    prefMgr.setSimplePreferenceState(PRINT_LOCAL_VARIABLES_OPTION, printLocalVariables.isSelected());
232                });
233            }
234        });
235
236        JCheckBox printSystemNames = new JCheckBox(Bundle.getMessage("LogixNG_Browse_PrintSystemNames"));
237        printSystemNames.setSelected(_printTreeSettings._printSystemNames);
238        printSystemNames.addChangeListener((event) -> {
239            if (_printTreeSettings._printSystemNames != printSystemNames.isSelected()) {
240                _printTreeSettings._printSystemNames = printSystemNames.isSelected();
241                InstanceManager.getOptionalDefault(UserPreferencesManager.class).ifPresent((prefMgr) -> {
242                    prefMgr.setSimplePreferenceState(PRINT_SYSTEM_NAMES_OPTION, printSystemNames.isSelected());
243                });
244                updateBrowserText(getText);
245            }
246        });
247
248        JCheckBox printDisabled = new JCheckBox(Bundle.getMessage("LogixNG_Browse_PrintDisabled"));
249        printDisabled.setSelected(_printTreeSettings._printDisabled);
250        printDisabled.addChangeListener((event) -> {
251            if (_printTreeSettings._printDisabled != printDisabled.isSelected()) {
252                _printTreeSettings._printDisabled = printDisabled.isSelected();
253                InstanceManager.getOptionalDefault(UserPreferencesManager.class).ifPresent((prefMgr) -> {
254                    prefMgr.setSimplePreferenceState(PRINT_DISABLED_OPTION, printDisabled.isSelected());
255                });
256                updateBrowserText(getText);
257            }
258        });
259
260        checkBoxPanel.add(printLineNumbers);
261        checkBoxPanel.add(printErrorHandling);
262        checkBoxPanel.add(printNotConnectedSockets);
263        checkBoxPanel.add(printLocalVariables);
264        checkBoxPanel.add(printSystemNames);
265        checkBoxPanel.add(printDisabled);
266
267        return checkBoxPanel;
268    }
269
270    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogixNGBrowseWindow.class);
271}