001package jmri.jmrit.beantable; 002 003import java.awt.event.ActionEvent; 004import java.beans.PropertyChangeEvent; 005import java.beans.PropertyChangeListener; 006 007import javax.swing.*; 008import javax.swing.table.TableRowSorter; 009 010import jmri.*; 011import jmri.jmrit.beantable.signalmast.SignalMastLogicTableDataModel; 012import jmri.jmrit.display.layoutEditor.LayoutBlockManager; 013import jmri.managers.DefaultSignalMastLogicManager; 014import jmri.util.ThreadingUtil; 015import jmri.util.JmriJFrame; 016import jmri.util.swing.JmriJOptionPane; 017 018public class SignalMastLogicTableAction extends AbstractTableAction<SignalMastLogic> { 019 020 /** 021 * Create an action with a specific title. 022 * <p> 023 * Note that the argument is the Action title, not the title of the 024 * resulting frame. Perhaps this should be changed? 025 * 026 * @param s title of the action 027 */ 028 public SignalMastLogicTableAction(String s) { 029 super(s); 030 } 031 032 public SignalMastLogicTableAction() { 033 this(Bundle.getMessage("TitleSignalMastLogicTable")); 034 } 035 036 @Override 037 public void actionPerformed(ActionEvent e) { 038 // create the JTable model, with changes for specific NamedBean 039 createModel(); 040 TableRowSorter<BeanTableDataModel<SignalMastLogic>> sorter = new TableRowSorter<>(m); 041 JTable dataTable = m.makeJTable(m.getMasterClassName(), m, sorter); 042 // create the frame 043 f = new jmri.jmrit.beantable.BeanTableFrame<SignalMastLogic>(m, helpTarget(), dataTable) { 044 }; 045 setMenuBar(f); 046 setTitle(); 047 addToFrame(f); 048 f.pack(); 049 f.setVisible(true); 050 } 051 052 /** 053 * Insert a table specific Tools menu. Account for the Window and Help 054 * menus, which are already added to the menu bar as part of the creation of 055 * the JFrame, by adding the Tools menu 2 places earlier unless the table is 056 * part of the ListedTableFrame, that adds the Help menu later on. 057 * 058 * @param f the JFrame of this table 059 */ 060 @Override 061 public void setMenuBar(BeanTableFrame<SignalMastLogic> f) { 062 final JmriJFrame finalF = f; // needed for anonymous ActionListener class 063 JMenuBar menuBar = f.getJMenuBar(); 064 int pos = menuBar.getMenuCount() - 1; // count the number of menus to insert the TableMenu before 'Window' and 'Help' 065 int offset = 1; 066 log.debug("setMenuBar number of menu items = {}", pos); 067 for (int i = 0; i <= pos; i++) { 068 if (menuBar.getComponent(i) instanceof JMenu) { 069 if (((AbstractButton) menuBar.getComponent(i)).getText().equals(Bundle.getMessage("MenuHelp"))) { 070 offset = -1; // correct for use as part of ListedTableAction where the Help Menu is not yet present 071 } 072 } 073 } 074 JMenu pathMenu = new JMenu(Bundle.getMessage("MenuTools")); 075 menuBar.add(pathMenu, pos + offset); 076 JMenuItem item = new JMenuItem(Bundle.getMessage("MenuItemAutoGen")); 077 pathMenu.add(item); 078 item.addActionListener( e -> autoCreatePairs(finalF)); 079 item = new JMenuItem(Bundle.getMessage("MenuItemAutoGenSections")); 080 pathMenu.add(item); 081 item.addActionListener( e -> { 082 ((DefaultSignalMastLogicManager) InstanceManager.getDefault(SignalMastLogicManager.class)).generateSection(); 083 InstanceManager.getDefault(SectionManager.class).generateBlockSections(); 084 JmriJOptionPane.showMessageDialog(finalF, Bundle.getMessage("SectionGenerationComplete")); 085 }); 086 JMenuItem setSMLDirSensors = new JMenuItem(Bundle.getMessage("MenuItemAddDirectionSensors")); 087 pathMenu.add(setSMLDirSensors); 088 setSMLDirSensors.addActionListener( e -> { 089 int n = InstanceManager.getDefault(SignalMastLogicManager.class).setupSignalMastsDirectionSensors(); 090 if (n > 0) { 091 JmriJOptionPane.showMessageDialog(finalF, java.text.MessageFormat.format( 092 Bundle.getMessage("MenuItemAddDirectionSensorsErrorCount"), n), 093 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 094 } 095 }); 096 097 } 098 099 @Override 100 protected void createModel() { 101 m = new SignalMastLogicTableDataModel(); 102 } 103 104 @Override 105 protected void setTitle() { 106 f.setTitle(Bundle.getMessage("TitleSignalMastLogicTable")); 107 } 108 109 @Override 110 protected String helpTarget() { 111 return "package.jmri.jmrit.beantable.SignalMastLogicTable";// NOI18N 112 } 113 114 @Override 115 protected void addPressed(ActionEvent e) { 116 sigLog.setMast(null, null); 117 sigLog.actionPerformed(e); 118 } 119 120 private JmriJFrame signalMastLogicFrame = null; 121 private JLabel sourceLabel = new JLabel(); 122 123 void autoCreatePairs(JmriJFrame f) { 124 if (!InstanceManager.getDefault(LayoutBlockManager.class).isAdvancedRoutingEnabled()) { 125 int response = JmriJOptionPane.showConfirmDialog(f, Bundle.getMessage("EnableLayoutBlockRouting"), 126 Bundle.getMessage("TitleBlockRouting"), JmriJOptionPane.YES_NO_OPTION); 127 if (response == 0) { 128 InstanceManager.getDefault(LayoutBlockManager.class).enableAdvancedRouting(true); 129 JmriJOptionPane.showMessageDialog(f, Bundle.getMessage("LayoutBlockRoutingEnabled")); 130 } else { 131 return; 132 } 133 } 134 signalMastLogicFrame = new JmriJFrame(Bundle.getMessage("DiscoverSignalMastPairs"), false, false); 135 signalMastLogicFrame.setPreferredSize(null); 136 JPanel panel1 = new JPanel(); 137 sourceLabel = new JLabel(Bundle.getMessage("DiscoveringSignalMastPairs")); 138 panel1.add(sourceLabel); 139 signalMastLogicFrame.add(panel1); 140 signalMastLogicFrame.pack(); 141 signalMastLogicFrame.setVisible(true); 142 143 final JCheckBox genSect = new JCheckBox(Bundle.getMessage("AutoGenSectionAfterLogic")); 144 genSect.setToolTipText(Bundle.getMessage("AutoGenSectionAfterLogicToolTip")); 145 Object[] params = {Bundle.getMessage("AutoGenSignalMastLogicMessage"), " ", genSect}; 146 int retval = JmriJOptionPane.showConfirmDialog(f, params, Bundle.getMessage("AutoGenSignalMastLogicTitle"), 147 JmriJOptionPane.YES_NO_OPTION); 148 149 if ( retval == JmriJOptionPane.YES_OPTION ) { 150 InstanceManager.getDefault(SignalMastLogicManager.class).addPropertyChangeListener(propertyGenerateListener); 151 // This process can take some time, so we do split it off then return to Swing/AWT 152 Runnable r = () -> { 153 //While the global discovery is taking place we remove the listener as this can result in a race condition. 154 ((SignalMastLogicTableDataModel)m).setSuppressUpdate(true); 155 try { 156 InstanceManager.getDefault(SignalMastLogicManager.class).automaticallyDiscoverSignallingPairs(); 157 } catch (JmriException e) { 158 // Notify of problem 159 try { 160 SwingUtilities.invokeAndWait(() -> { 161 InstanceManager.getDefault(SignalMastLogicManager.class).removePropertyChangeListener(propertyGenerateListener); 162 JmriJOptionPane.showMessageDialog(f, e.toString()); 163 signalMastLogicFrame.setVisible(false); 164 }); 165 } catch (java.lang.reflect.InvocationTargetException ex) { 166 log.error("failed to notify of problem with automaticallyDiscoverSignallingPairs", ex); 167 } catch (InterruptedException ex) { 168 log.error("interrupted while notifying of problem with automaticallyDiscoverSignallingPairs", ex); 169 } 170 } 171 172 // process complete, update GUI 173 try { 174 SwingUtilities.invokeAndWait(() -> { 175 m.updateNameList(); 176 ((SignalMastLogicTableDataModel)m).setSuppressUpdate(false); 177 m.fireTableDataChanged(); 178 if (genSect.isSelected()) { 179 ((DefaultSignalMastLogicManager) InstanceManager.getDefault(SignalMastLogicManager.class)).generateSection(); 180 InstanceManager.getDefault(SectionManager.class).generateBlockSections(); 181 } 182 }); 183 } catch (java.lang.reflect.InvocationTargetException ex) { 184 log.error("failed to update at end of automaticallyDiscoverSignallingPairs", ex); 185 } catch (InterruptedException ex) { 186 log.error("interrupted during update at end of automaticallyDiscoverSignallingPairs", ex); 187 } 188 }; 189 Thread thr = ThreadingUtil.newThread(r, "Discover Signal Mast Logic"); // NOI18N 190 thr.start(); 191 192 } else { 193 signalMastLogicFrame.setVisible(false); 194 } 195 } 196 197 private final PropertyChangeListener propertyGenerateListener = new PropertyChangeListener() { 198 @Override 199 public void propertyChange(PropertyChangeEvent evt) { 200 if (SignalMastLogicManager.PROPERTY_AUTO_GENERATE_COMPLETE.equals(evt.getPropertyName())) { 201 if (signalMastLogicFrame != null) { 202 signalMastLogicFrame.setVisible(false); 203 } 204 InstanceManager.getDefault(SignalMastLogicManager.class).removePropertyChangeListener(this); 205 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("SignalMastPairGenerationComplete")); 206 } else if (SignalMastLogicManager.PROPERTY_AUTO_GENERATE_UPDATE.equals(evt.getPropertyName())) { 207 sourceLabel.setText((String) evt.getNewValue()); 208 signalMastLogicFrame.pack(); 209 signalMastLogicFrame.repaint(); 210 } 211 } 212 }; 213 214 private final jmri.jmrit.signalling.SignallingAction sigLog = new jmri.jmrit.signalling.SignallingAction(); 215 216 @Override 217 protected String getClassName() { 218 return SignalMastLogicTableAction.class.getName(); 219 } 220 221 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SignalMastLogicTableAction.class); 222}