001package jmri.jmrix.dccpp.swing.messages; 002 003import java.awt.Frame; 004 005import javax.annotation.CheckForNull; 006import javax.swing.JMenuItem; 007import javax.swing.JPopupMenu; 008 009import jmri.InstanceManager; 010import jmri.InvokeOnGuiThread; 011import jmri.UserPreferencesManager; 012import jmri.configurexml.JmriConfigureXmlException; 013import jmri.jmrix.dccpp.DCCppSystemConnectionMemo; 014import jmri.jmrix.dccpp.swing.messages.configurexml.MessagesConfigurationXml; 015import jmri.util.JmriJFrame; 016import jmri.util.swing.*; 017 018import org.jdom2.Element; 019 020/** Window showing EXRAIL MESSAGE() broadcasts, one per DCC-EX connection. */ 021public class MessagesFrame extends JmriJFrame { 022 023 private final DCCppSystemConnectionMemo _memo; 024 private final MessagesPanel _messagesPanel; 025 private JPopupMenu popup; 026 027 private static String getElementName(DCCppSystemConnectionMemo memo) { 028 return "dccex_messages_config" + "___" + memo.getSystemPrefix(); 029 } 030 031 public MessagesFrame(DCCppSystemConnectionMemo memo) { 032 // save window position but not size, include prefix in title for multiple connections 033 super(false, true, Bundle.getMessage("MessagesFrameTitle") + " (" + memo.getSystemPrefix() + ")"); 034 _memo = memo; 035 _messagesPanel = new MessagesPanel(this, false); 036 _messagesPanel.setMemo(memo); 037 } 038 039 public DCCppSystemConnectionMemo getMemo() { 040 return _memo; 041 } 042 043 public MessagesPanel getMessagesPanel() { 044 return _messagesPanel; 045 } 046 047 /** Find the open Messages window for this connection, or null. */ 048 @CheckForNull 049 public static MessagesFrame findFrame(DCCppSystemConnectionMemo memo) { 050 for (MessagesFrame f : JmriJFrame.getFrameList(MessagesFrame.class)) { 051 if (f.getMemo() == memo) { 052 return f; 053 } 054 } 055 return null; 056 } 057 058 /** Open (or bring forward) the Messages window; initialMessage is only added to a newly created window. */ 059 @InvokeOnGuiThread 060 public static MessagesFrame showFrame(DCCppSystemConnectionMemo memo, @CheckForNull String initialMessage) { 061 MessagesFrame frame = findFrame(memo); 062 if (frame == null) { 063 frame = new MessagesFrame(memo); 064 frame.initComponents(); 065 if (initialMessage != null) { 066 frame.getMessagesPanel().addMessage(initialMessage); 067 } 068 frame.setVisible(true); 069 } 070 frame.setExtendedState(Frame.NORMAL); 071 frame.toFront(); 072 return frame; 073 } 074 075 /** Whether the window should open itself when a message arrives; true unless the user turned it off. */ 076 public static boolean isAutoOpen(DCCppSystemConnectionMemo memo) { 077 MessagesFrame frame = findFrame(memo); 078 if (frame != null) { 079 return frame.getMessagesPanel().isAutoOpen(); 080 } 081 UserPreferencesManager p = InstanceManager.getNullableDefault(UserPreferencesManager.class); 082 if (p == null) { 083 return true; 084 } 085 Element e = p.loadElement(getElementName(memo)); 086 if (e == null) { 087 return true; 088 } 089 Element config = e.getChild("dccex_messages_config"); 090 String value = config != null ? config.getChildTextTrim("autoOpen") : null; 091 return value == null || "true".equals(value); 092 } 093 094 @Override 095 public void dispose() { 096 storeSettings(); 097 _messagesPanel.dispose(); 098 super.dispose(); 099 } 100 101 private void storeSettings() { 102 InstanceManager.getOptionalDefault(UserPreferencesManager.class).ifPresent(p -> { 103 Element parent = new Element(getElementName(_memo), UserPreferencesManager.GENERIC_NAMESPACE); 104 parent.addContent(MessagesConfigurationXml.store(_messagesPanel)); 105 p.storeElement(parent); 106 }); 107 } 108 109 void editSettings() { 110 ConfigureMessages.editConfigureMessages(null, _messagesPanel, this::storeSettings); 111 } 112 113 /** {@inheritDoc} */ 114 @Override 115 public void initComponents() { 116 super.initComponents(); 117 _messagesPanel.initComponents(); 118 add(_messagesPanel); 119 120 popup = new JPopupMenu(); 121 JMenuItem editItem = new JMenuItem(Bundle.getMessage("EditMessages")); 122 editItem.addActionListener(evt -> editSettings()); 123 popup.add(editItem); 124 JMenuItem clearItem = new JMenuItem(Bundle.getMessage("ClearMessages")); 125 clearItem.addActionListener(evt -> _messagesPanel.clearMessages()); 126 popup.add(clearItem); 127 128 JmriMouseListener popupListener = new JmriMouseAdapter() { 129 @Override 130 public void mousePressed(JmriMouseEvent e) { 131 maybeShowPopup(e); 132 } 133 134 @Override 135 public void mouseReleased(JmriMouseEvent e) { 136 maybeShowPopup(e); 137 } 138 139 private void maybeShowPopup(JmriMouseEvent e) { 140 if (e.isPopupTrigger()) { 141 popup.show(e.getComponent(), e.getX(), e.getY()); 142 } 143 } 144 }; 145 _messagesPanel.addMouseListener(JmriMouseListener.adapt(popupListener)); 146 147 pack(); 148 149 InstanceManager.getOptionalDefault(UserPreferencesManager.class).ifPresent(p -> { 150 Element e = p.loadElement(getElementName(_memo)); 151 if (e != null) { 152 try { 153 MessagesConfigurationXml.load(_messagesPanel, e, true); 154 } catch (JmriConfigureXmlException ex) { 155 log.error("Unexpected exception during loading of settings", ex); 156 } 157 } 158 }); 159 } 160 161 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MessagesFrame.class); 162 163}