001package jmri.jmrix.loconet.loconetovertcp;
002
003import java.awt.Component;
004import java.awt.event.ActionEvent;
005import javax.swing.BoxLayout;
006import javax.swing.JButton;
007import javax.swing.JLabel;
008import javax.swing.JPanel;
009import jmri.InstanceManager;
010import jmri.util.JmriJFrame;
011
012/**
013 * Frame displaying the status of the a LocoNet over TCP server.
014 * <p>
015 * Some of the message formats used in this class are Copyright Digitrax, Inc.
016 * and used with permission as part of the JMRI project. That permission does
017 * not extend to uses in other software products. If you wish to use this code,
018 * algorithm or these message formats outside of JMRI, please contact Digitrax
019 * Inc for separate permission.
020 *
021 * @author Bob Jacobsen Copyright (C) 2003, 2004
022 * @author Alex Shepherd Copyright (C) 2006
023 * @author Randall Wood Copyright (C) 2017
024 */
025public class LnTcpServerFrame extends JmriJFrame {
026
027    private final JLabel portNumberLabel = new JLabel(Bundle.getMessage("PortLabel", 1234));
028    private final JLabel statusLabel = new JLabel(Bundle.getMessage("StatusLabel", Bundle.getMessage("Stopped"), 0));
029
030    private final JButton startButton = new JButton(Bundle.getMessage("StartServer"));
031    private final JButton stopButton = new JButton(Bundle.getMessage("StopServer"));
032    private final LnTcpServer server;
033    private final LnTcpServerListener listener;
034
035    /**
036     * Create a LocoNet over TCP server status window.
037     *
038     * @param server the server to monitor
039     */
040    public LnTcpServerFrame(LnTcpServer server) {
041        super(Bundle.getMessage("ServerAction"));
042        this.server = server;
043
044        super.getContentPane().setLayout(new BoxLayout(super.getContentPane(), BoxLayout.Y_AXIS));
045
046        // add GUI items
047        portNumberLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
048        super.getContentPane().add(portNumberLabel);
049
050        JPanel panel = new JPanel();
051        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
052        panel.add(startButton);
053        panel.add(stopButton);
054        panel.setAlignmentX(Component.CENTER_ALIGNMENT);
055        super.getContentPane().add(panel);
056
057        statusLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
058        super.getContentPane().add(statusLabel);
059
060        startButton.addActionListener((ActionEvent a) -> {
061            server.enable();
062        });
063
064        stopButton.addActionListener((ActionEvent a) -> {
065            server.disable();
066        });
067
068        this.listener = new LnTcpServerListener() {
069            @Override
070            public void notifyServerStateChanged(LnTcpServer s) {
071                if (s.equals(LnTcpServerFrame.this.server)) {
072                    javax.swing.SwingUtilities.invokeLater(() -> {
073                        LnTcpServerFrame.this.updateServerStatus(s);
074                    });
075                }
076            }
077
078            @Override
079            public void notifyClientStateChanged(LnTcpServer s) {
080                if (s.equals(LnTcpServerFrame.this.server)) {
081                    javax.swing.SwingUtilities.invokeLater(() -> {
082                        LnTcpServerFrame.this.updateClientStatus(s);
083                    });
084                }
085            }
086        };
087        server.addStateListener(listener);
088        this.updateServerStatus(server);
089        super.pack();
090    }
091
092    @Override
093    public void windowClosing(java.awt.event.WindowEvent e) {
094        setVisible(false);
095        this.server.removeStateListener(this.listener);
096        dispose();
097        super.windowClosing(e);
098        InstanceManager.deregister(this, LnTcpServerFrame.class);
099    }
100
101    @Override
102    public void dispose() {
103        super.dispose();
104    }
105
106    /**
107     * Get the server status window for the default LocoNet over TCP server.
108     *
109     * @return the default server frame instance, creating it if needed
110     */
111    static public synchronized LnTcpServerFrame getDefault() {
112        return InstanceManager.getOptionalDefault(LnTcpServerFrame.class).orElseGet(() -> {
113            return InstanceManager.setDefault(LnTcpServerFrame.class, new LnTcpServerFrame(LnTcpServer.getDefault()));
114        });
115    }
116
117    private void updateServerStatus(LnTcpServer s) {
118        portNumberLabel.setText(Bundle.getMessage("PortLabel", s.getPort()));
119        startButton.setEnabled(!s.isEnabled());
120        stopButton.setEnabled(s.isEnabled());
121        this.updateClientStatus(s);
122    }
123
124    private void updateClientStatus(LnTcpServer s) {
125        statusLabel.setText(Bundle.getMessage("StatusLabel", (s.isEnabled() ? Bundle.getMessage("Running") : Bundle.getMessage("Stopped")), s.getClientCount()));
126    }
127
128}