001package jmri.jmrix.openlcb.swing; 002 003import java.awt.event.WindowEvent; 004import java.awt.event.ActionEvent; 005import java.awt.event.ActionListener; 006 007import javax.swing.JButton; 008import javax.swing.JFormattedTextField; 009import javax.swing.JPanel; 010import javax.swing.JTextField; 011import javax.swing.Timer; 012 013import jmri.ShutDownTask; 014import jmri.jmrix.can.CanSystemConnectionMemo; 015import jmri.util.JmriJFrame; 016import jmri.util.swing.WrapLayout; 017 018import org.openlcb.NodeID; 019import org.openlcb.OlcbInterface; 020import org.openlcb.cdi.impl.ConfigRepresentation; 021import org.openlcb.cdi.swing.CdiPanel; 022 023/** 024 * Shared code for creating UI elements from different places in the application. 025 * <p> 026 * Created by bracz on 11/21/16. 027 */ 028 029public class ClientActions { 030 private final OlcbInterface iface; 031 private final CanSystemConnectionMemo memo; 032 033 public ClientActions(OlcbInterface iface, CanSystemConnectionMemo memo) { 034 this.iface = iface; 035 this.memo = memo; 036 } 037 038 CdiPanel cdiPanel; 039 ShutDownTask shutDownTask; 040 041 public void openCdiWindow(NodeID destNode, String description) { 042// final java.util.ArrayList<JButton> readList = new java.util.ArrayList<>(); 043 final java.util.ArrayList<JButton> sensorButtonList = new java.util.ArrayList<>(); 044 final java.util.ArrayList<JButton> turnoutButtonList = new java.util.ArrayList<>(); 045 046 JmriJFrame f = new NodeSpecificFrame(destNode); 047 f.setTitle(Bundle.getMessage("CdiPanelConfigure", description)); 048 f.setLayout(new javax.swing.BoxLayout(f.getContentPane(), javax.swing.BoxLayout.Y_AXIS)); 049 f.addHelpMenu("package.jmri.jmrix.openlcb.swing.networktree.NetworkTreePane_CDItool", true); 050 051 cdiPanel = new CdiPanel(){ 052 // override and extend window closing behavior 053 @Override 054 protected void targetWindowClosingEvent(WindowEvent evt) { // evt is ignored here 055 log.trace("overridden targetWindowClosingEvent runs"); 056 super.targetWindowClosingEvent(evt); 057 } 058 // when actually closing the window, also deregister the safety shutdown class 059 @Override 060 public void release() { 061 super.release(); 062 jmri.InstanceManager.getDefault(jmri.ShutDownManager.class).deregister(shutDownTask); 063 } 064 }; 065 f.add(cdiPanel); 066 cdiPanel.setEventTable(iface.getNodeStore().getSimpleNodeIdent(destNode).getUserName(), 067 iface.getEventTable()); 068 069 // Add a shutdown task to handle "Cancel" selections should there be unsaved 070 // changed at Shutdown 071 jmri.InstanceManager.getDefault(jmri.ShutDownManager.class).register( 072 shutDownTask = new ShutDownTask() { 073 @Override 074 public String getName() { return "CDI Window Check"; } 075 @Override 076 public Boolean call() { 077 log.trace("call( checks contents)"); 078 boolean result = cdiPanel.checkOnWindowClosing(); // true to continue shutdown, false to not 079 if (result) { 080 // you don't want a second check on automatic window closing during shutdown 081 cdiPanel.setWindowCloseCheckAlreadyHandled(); 082 } 083 return result; 084 } 085 086 @Override 087 public void propertyChange(java.beans.PropertyChangeEvent e) { 088 // don't care if somebody else cancels 089 } 090 091 @Override 092 public void run() { 093 // we're shutting down, nothing to do 094 } 095 }); 096 097 // create an object to add "New Sensor" buttons 098 CdiPanel.GuiItemFactory factory = new CdiPanel.GuiItemFactory() { 099 private boolean haveButtons = false; 100 @Override 101 public JButton handleReadButton(JButton button) { 102// readList.add(button); 103 return button; 104 } 105 106 @Override 107 public JButton handleWriteButton(JButton button) { 108 return button; 109 } 110 111 @Override 112 public void handleGroupPaneStart(JPanel pane) { 113 this.gpane = pane; 114 evt1 = null; 115 evt2 = null; 116 desc = null; 117 } 118 119 @Override 120 public void handleGroupPaneEnd(JPanel pane) { 121 if (gpane != null && evt1 != null && evt2 != null && desc != null) { 122 JPanel p = new JPanel(); 123 p.setLayout(new WrapLayout()); 124 p.setAlignmentX(-1.0f); 125 pane.add(p); 126 JButton button = new JButton(Bundle.getMessage("CdiPanelMakeSensor")); 127 p.add(button); 128 sensorButtonList.add(button); 129 button.addActionListener(new java.awt.event.ActionListener() { 130 @Override 131 public void actionPerformed(java.awt.event.ActionEvent e) { 132 jmri.Sensor sensor = jmri.InstanceManager.sensorManagerInstance() 133 .provideSensor(memo.getSystemPrefix() + "S" + mevt1.getText() + ";" + mevt2.getText()); 134 if (mdesc.getText().length() > 0) { 135 sensor.setUserName(mdesc.getText()); 136 } 137 log.info("make sensor MS{};{} [{}]", mevt1.getText(), mevt2.getText(), mdesc.getText()); 138 } 139 140 final JTextField mdesc = desc; 141 final JFormattedTextField mevt1 = evt1; 142 final JFormattedTextField mevt2 = evt2; 143 }); 144 button = new JButton(Bundle.getMessage("CdiPanelMakeTurnout")); 145 p.add(button); 146 turnoutButtonList.add(button); 147 button.addActionListener(new java.awt.event.ActionListener() { 148 @Override 149 public void actionPerformed(java.awt.event.ActionEvent e) { 150 jmri.Turnout turnout = jmri.InstanceManager.turnoutManagerInstance() 151 .provideTurnout(memo.getSystemPrefix() + "T" + mevt1.getText() + ";" + mevt2.getText()); 152 if (mdesc.getText().length() > 0) { 153 turnout.setUserName(mdesc.getText()); 154 } 155 log.info("make turnout MT{};{} [{}]", mevt1.getText(), mevt2.getText(), mdesc.getText()); 156 } 157 158 final JTextField mdesc = desc; 159 final JFormattedTextField mevt1 = evt1; 160 final JFormattedTextField mevt2 = evt2; 161 }); 162 if (!haveButtons) { 163 haveButtons = true; 164 cdiPanel.addButtonToFooter(buttonForList(sensorButtonList, Bundle.getMessage("CdiPanelMakeAllSensors"))); 165 cdiPanel.addButtonToFooter(buttonForList(turnoutButtonList, Bundle.getMessage("CdiPanelMakeAllTurnouts"))); 166 } 167 gpane = null; 168 evt1 = null; 169 evt2 = null; 170 desc = null; 171 } 172 } 173 174 @Override 175 public JFormattedTextField handleEventIdTextField(JFormattedTextField field) { 176 if (evt1 == null) { 177 evt1 = field; 178 } else if (evt2 == null) { 179 evt2 = field; 180 } else { 181 gpane = null; // flag too many 182 } 183 return field; 184 } 185 186 @Override 187 public JTextField handleStringValue(JTextField value) { 188 desc = value; 189 return value; 190 } 191 192 @Override 193 /** 194 * Make a sensor from a single Event ID. 195 * Set the user name from the CDI description (if available) 196 * {@inheritDoc} 197 */ 198 public void makeSensor(String ev, String mdesc) { 199 jmri.Sensor sensor = 200 jmri.InstanceManager.sensorManagerInstance() 201 .provideSensor(memo.getSystemPrefix() + "S" + ev); 202 if (mdesc.length() > 0) { 203 sensor.setUserName(mdesc); 204 } 205 log.debug("make sensor MS{} [{}]", ev, mdesc); 206 } 207 208 JPanel gpane = null; 209 JTextField desc = null; 210 JFormattedTextField evt1 = null; 211 JFormattedTextField evt2 = null; 212 }; 213 ConfigRepresentation rep = iface.getConfigForNode(destNode); 214 215 cdiPanel.initComponents(rep, factory); 216 217 f.pack(); 218 f.setVisible(true); 219 } 220 221 JButton buttonForList(final java.util.ArrayList<JButton> list, String label) { 222 JButton b = new JButton(label); 223 b.addActionListener(e -> { 224 int delay = 0; //milliseconds 225 for (final JButton b1 : list) { 226 227 ActionListener taskPerformer = new ActionListener() { 228 @Override 229 public void actionPerformed(ActionEvent evt) { 230 target.doClick(); 231 } 232 final JButton target = b1; 233 }; 234 Timer t = new Timer(delay, taskPerformer); 235 t.setRepeats(false); 236 t.start(); 237 delay = delay + 150; 238 } 239 }); 240 return b; 241 } 242 243 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ClientActions.class); 244}