001package jmri.jmrit.beantable; 002 003import java.awt.Frame; 004import java.awt.GridBagLayout; 005import java.awt.event.ActionEvent; 006import java.text.MessageFormat; 007import java.util.ArrayList; 008import java.util.List; 009import java.util.ResourceBundle; 010import javax.swing.AbstractAction; 011import javax.swing.BorderFactory; 012import javax.swing.BoxLayout; 013import javax.swing.JButton; 014import javax.swing.JComboBox; 015import javax.swing.JPanel; 016import javax.swing.event.ChangeEvent; 017import jmri.InstanceManager; 018import jmri.Reporter; 019import jmri.ReporterManager; 020import jmri.jmrit.operations.OperationsFrame; 021import jmri.jmrit.operations.OperationsPanel; 022import jmri.util.PhysicalLocation; 023import jmri.util.PhysicalLocationPanel; 024import jmri.util.swing.JmriJOptionPane; 025 026/** 027 * Swing action to create a SetPhysicalLocation dialog. 028 * 029 * @author Bob Jacobsen Copyright (C) 2001 030 * @author Daniel Boudreau Copyright (C) 2010 031 * @author Mark Underwood Copyright (C) 2011 032 */ 033public class SetPhysicalLocationAction extends AbstractAction { 034 035 Reporter _reporter; 036 037 static ResourceBundle rb = ResourceBundle.getBundle("jmri.jmrit.beantable.JmritBeantablePhysicalLocationBundle"); 038 039 /** 040 * Constructor. 041 * 042 * @param s title of the action 043 * @param reporter {@link Reporter} to use 044 */ 045 public SetPhysicalLocationAction(String s, Reporter reporter) { 046 super(s); 047 _reporter = reporter; 048 } 049 050 SetPhysicalLocationFrame f = null; 051 052 /** 053 * Action method. 054 * 055 * @param e the associated {@link ActionEvent} that triggered this action 056 */ 057 @Override 058 public void actionPerformed(ActionEvent e) { 059 // create a copy route frame 060 if (f == null || !f.isVisible()) { 061 f = new SetPhysicalLocationFrame(_reporter); 062 f.setVisible(true); 063 } 064 f.setExtendedState(Frame.NORMAL); 065 } 066 067 /** 068 * Frame for setting train physical location coordinates for a Reporter. 069 * 070 * @author Bob Jacobsen Copyright (C) 2001 071 * @author Daniel Boudreau Copyright (C) 2010 072 * @author Mark Underwood Copyright (C) 2011 073 * 074 */ 075 private static class SetPhysicalLocationFrame extends OperationsFrame { 076 077 /** 078 * Frame Constructor. 079 */ 080 public SetPhysicalLocationFrame(Reporter reporter) { 081 super(rb.getString("MenuSetPhysicalLocation"), new SetPhysicalLocationPanel(reporter)); 082 083 // add help menu to window 084 addHelpMenu("package.jmri.jmrit.operations.Operations_SetTrainIconCoordinates", true); // fix this later 085 086 super.pack(); 087 } 088 } 089 090 private static class SetPhysicalLocationPanel extends OperationsPanel { 091 092 Reporter _reporter; 093 094 String emptyReporterString = "(No Reporters)"; 095 096 List<Reporter> _reporterList = new ArrayList<>(); 097 098 // labels 099 // text field 100 // check boxes 101 // major buttons 102 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 103 JButton closeButton = new JButton(Bundle.getMessage("ButtonClose")); 104 105 // combo boxes 106 JComboBox<String> reporterBox = getReporterComboBox(); 107 108 // Spinners 109 PhysicalLocationPanel physicalLocation; 110 111 public SetPhysicalLocationPanel(Reporter l) { 112 113 // Store the location (null if called from the list view) 114 _reporter = l; 115 116 // general GUI config 117 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 118 119 // set tool tips 120 saveButton.setToolTipText(rb.getString("TipSaveButton")); 121 closeButton.setToolTipText(rb.getString("TipCloseButton")); 122 123 // Set up the panels 124 JPanel pLocation = new JPanel(); 125 pLocation.setBorder(BorderFactory.createTitledBorder(rb.getString("ReporterName"))); 126 pLocation.setToolTipText(rb.getString("TipSelectReporter")); 127 pLocation.add(reporterBox); 128 129 physicalLocation = new PhysicalLocationPanel(rb.getString("PhysicalLocation")); 130 physicalLocation.setToolTipText(rb.getString("TipPhysicalLocation")); 131 physicalLocation.setVisible(true); 132 133 JPanel pControl = new JPanel(); 134 pControl.setLayout(new GridBagLayout()); 135 pControl.setBorder(BorderFactory.createTitledBorder("")); 136 addItem(pControl, saveButton, 1, 0); 137 addItem(pControl, closeButton, 2, 0); 138 139 add(pLocation); 140 add(physicalLocation); 141 add(pControl); 142 143 // setup buttons 144 saveButton.addActionListener(this::saveButtonActionPerformed); 145 closeButton.addActionListener(this::closeButtonActionPerformed); 146 147 // setup combo box 148 addComboBoxAction(reporterBox); 149 reporterBox.setSelectedIndex(0); 150 151 if (_reporter != null) { 152 reporterBox.setSelectedItem(_reporter); 153 } 154 155 setVisible(true); 156 } 157 158 /** 159 * Construct the combo box with the list of available Reporters. 160 */ 161 protected JComboBox<String> getReporterComboBox() { 162 ReporterManager mgr = InstanceManager.getDefault(jmri.ReporterManager.class); 163 List<String> displayList = new ArrayList<>(); 164 for (Reporter r : mgr.getNamedBeanSet()) { 165 if (r != null) { 166 _reporterList.add(r); 167 displayList.add(r.getDisplayName()); 168 } 169 } 170 if (displayList.isEmpty()) { 171 displayList.add(emptyReporterString); 172 saveButton.setEnabled(false); 173 } 174 String[] sa = new String[displayList.size()]; 175 displayList.toArray(sa); 176 JComboBox<String> retv = new JComboBox<>(sa); 177 return (retv); 178 179 } 180 181 /** 182 * Close button action. 183 */ 184 public void closeButtonActionPerformed(ActionEvent ae) { 185 JmriJOptionPane.showMessageDialog(this, 186 rb.getString("CloseButtonSaveWarning"), 187 rb.getString("CloseButtonSaveWarningTitle"), 188 JmriJOptionPane.WARNING_MESSAGE); 189 dispose(); 190 } 191 192 /** 193 * Save button action -> save this Reporter's location. 194 */ 195 public void saveButtonActionPerformed(ActionEvent ae) { 196 // check to see if a location has been selected 197 if (reporterBox.getSelectedItem() == null 198 || reporterBox.getSelectedItem().equals("")) { 199 JmriJOptionPane.showMessageDialog(this, 200 rb.getString("SelectLocationToEdit"), 201 rb.getString("NoLocationSelected"), 202 JmriJOptionPane.ERROR_MESSAGE); 203 return; 204 } 205 Reporter l = getReporterFromList(); 206 if (l == null) { 207 return; 208 } 209 int value = JmriJOptionPane.showConfirmDialog(null, MessageFormat.format(rb.getString("UpdatePhysicalLocation"), 210 new Object[]{l.getDisplayName()}), rb.getString("SaveLocation?"), JmriJOptionPane.YES_NO_OPTION); 211 if (value == JmriJOptionPane.YES_OPTION) { 212 saveSpinnerValues(l); 213 } 214 } 215 216 /** 217 * Get a Reporter from its name in the combo box. 218 */ 219 private Reporter getReporterFromList() { 220 String s = (String) reporterBox.getSelectedItem(); 221 // Since we don't have "getByDisplayName()" we need to do this in two steps 222 Reporter r = InstanceManager.getDefault(jmri.ReporterManager.class).getByDisplayName(s); 223 return (r); 224 } 225 226 /** 227 * Combo box action. 228 */ 229 @Override 230 public void comboBoxActionPerformed(ActionEvent ae) { 231 if (reporterBox.getSelectedItem() != null) { 232 if (reporterBox.getSelectedItem().equals("") || reporterBox.getSelectedItem().equals(emptyReporterString)) { 233 resetSpinners(); 234 } else { 235 Reporter l = getReporterFromList(); 236 loadSpinners(l); 237 } 238 } 239 } 240 241 /** 242 * Spinner change event. 243 */ 244 @Override 245 public void spinnerChangeEvent(ChangeEvent ae) { 246 if (ae.getSource() == physicalLocation) { 247 Reporter l = getReporterFromList(); 248 if (l != null) { 249 PhysicalLocation.setBeanPhysicalLocation(physicalLocation.getValue(), l); 250 } 251 } 252 } 253 254 /** 255 * Reset spinners to zero. 256 */ 257 private void resetSpinners() { 258 // Reset spinners to zero. 259 physicalLocation.setValue(new PhysicalLocation()); 260 } 261 262 /** 263 * Load spinners from an existing Reporter 264 */ 265 private void loadSpinners(Reporter r) { 266 log.debug("Load spinners Reporter location {}", r.getSystemName()); 267 physicalLocation.setValue(PhysicalLocation.getBeanPhysicalLocation(r)); 268 } 269 270 // Unused. Carried over from SetTrainIconPosition or whatever it was 271 // called... 272 /* 273 * private void spinnersEnable(boolean enable){ 274 * physicalLocation.setEnabled(enable); } 275 */ 276 /** 277 * Write spinner values to a Reporter. 278 */ 279 private void saveSpinnerValues(Reporter r) { 280 log.debug("Save train icons coordinates for location {}", r.getSystemName()); 281 PhysicalLocation.setBeanPhysicalLocation(physicalLocation.getValue(), r); 282 } 283 284 } 285 286 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SetPhysicalLocationAction.class); 287 288}