001package jmri.jmrit.operations.trains.tools; 002 003import java.awt.Dimension; 004import java.awt.GridBagLayout; 005import java.util.ArrayList; 006import java.util.List; 007 008import javax.swing.*; 009 010import jmri.InstanceManager; 011import jmri.jmrit.operations.OperationsFrame; 012import jmri.jmrit.operations.OperationsXml; 013import jmri.jmrit.operations.rollingstock.cars.CarTypes; 014import jmri.jmrit.operations.setup.Control; 015import jmri.jmrit.operations.setup.Setup; 016import jmri.jmrit.operations.trains.Train; 017import jmri.jmrit.operations.trains.TrainManager; 018import jmri.util.swing.JmriJOptionPane; 019 020/** 021 * Frame to display which trains service certain car types 022 * 023 * @author Dan Boudreau Copyright (C) 2009, 2022 024 */ 025public class TrainsByCarTypeFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 026 027 TrainManager trainManager = InstanceManager.getDefault(TrainManager.class); 028 029 ArrayList<JCheckBox> trainList = new ArrayList<>(); 030 JPanel trainCheckBoxes = new JPanel(); 031 032 // panels 033 JPanel pTrains; 034 035 // major buttons 036 JButton clearButton = new JButton(Bundle.getMessage("ClearAll")); 037 JButton setButton = new JButton(Bundle.getMessage("SelectAll")); 038 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 039 040 // check boxes 041 JCheckBox copyCheckBox = new JCheckBox(Bundle.getMessage("ButtonCopy")); 042 043 // combo boxes 044 JComboBox<String> typeComboBox = InstanceManager.getDefault(CarTypes.class).getComboBox(); 045 JComboBox<String> copyComboBox = InstanceManager.getDefault(CarTypes.class).getComboBox(); 046 047 public TrainsByCarTypeFrame() { 048 super(Bundle.getMessage("TitleModifyTrains")); 049 } 050 051 public void initComponents(String carType) { 052 053 // general GUI config 054 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 055 056 // Set up the panels 057 JPanel pCarType = new JPanel(); 058 pCarType.setLayout(new GridBagLayout()); 059 pCarType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Type"))); 060 061 JPanel pCarCopy = new JPanel(); 062 pCarCopy.setLayout(new GridBagLayout()); 063 addItem(pCarCopy, copyComboBox, 0, 0); 064 pCarCopy.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("CopyType"))); 065 066 addItem(pCarType, typeComboBox, 0, 0); 067 addItem(pCarType, copyCheckBox, 1, 0); 068 addItem(pCarType, pCarCopy, 2, 0); 069 typeComboBox.setSelectedItem(carType); 070 copyCheckBox.setToolTipText(Bundle.getMessage("TipCopyCarType")); 071 072 pTrains = new JPanel(); 073 pTrains.setLayout(new GridBagLayout()); 074 JScrollPane trainPane = new JScrollPane(pTrains); 075 trainPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 076 trainPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Trains"))); 077 updateTrains(); 078 079 JPanel pButtons = new JPanel(); 080 pButtons.setLayout(new GridBagLayout()); 081 pButtons.setBorder(BorderFactory.createEtchedBorder()); 082 083 addItem(pButtons, clearButton, 0, 0); 084 addItem(pButtons, setButton, 1, 0); 085 addItem(pButtons, saveButton, 2, 0); 086 087 getContentPane().add(pCarType); 088 getContentPane().add(trainPane); 089 getContentPane().add(pButtons); 090 091 // setup combo box 092 addComboBoxAction(typeComboBox); 093 addComboBoxAction(copyComboBox); 094 095 // setup buttons 096 addButtonAction(setButton); 097 addButtonAction(clearButton); 098 addButtonAction(saveButton); 099 100 // setup checkbox 101 addCheckBoxAction(copyCheckBox); 102 103 trainManager.addPropertyChangeListener(this); 104 InstanceManager.getDefault(CarTypes.class).addPropertyChangeListener(this); 105 106 // build menu 107 JMenuBar menuBar = new JMenuBar(); 108 JMenu toolMenu = new JMenu(Bundle.getMessage("MenuTools")); 109 toolMenu.add(new PrintTrainsByCarTypesAction(false)); 110 toolMenu.add(new PrintTrainsByCarTypesAction(true)); 111 menuBar.add(toolMenu); 112 setJMenuBar(menuBar); 113 addHelpMenu("package.jmri.jmrit.operations.Operations_ModifyTrainsByCarType", true); // NOI18N 114 115 setPreferredSize(null); 116 initMinimumSize(new Dimension(Control.panelWidth300, Control.panelHeight250)); 117 } 118 119 @Override 120 public void comboBoxActionPerformed(java.awt.event.ActionEvent ae) { 121 log.debug("combo box action"); 122 updateTrains(); 123 } 124 125 // Save, Delete, Add 126 @Override 127 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 128 if (ae.getSource() == saveButton) { 129 save(); 130 } 131 if (ae.getSource() == setButton) { 132 selectCheckboxes(true); 133 } 134 if (ae.getSource() == clearButton) { 135 selectCheckboxes(false); 136 } 137 } 138 139 /** 140 * Update the car types that trains and tracks service. Note that the 141 * checkbox name is the id of the train or track. 142 */ 143 private void save() { 144 if (copyCheckBox.isSelected() && 145 JmriJOptionPane.showConfirmDialog(this, Bundle.getMessage("CopyCarType", 146 typeComboBox.getSelectedItem(), copyComboBox.getSelectedItem()), 147 Bundle.getMessage("CopyCarTypeTitle"), 148 JmriJOptionPane.YES_NO_OPTION) != JmriJOptionPane.YES_OPTION) { 149 return; 150 } 151 log.debug("Save {} trains", trainList.size()); 152 removePropertyChangeTrains(); 153 // protected against concurrent operation by making a copy 154 for (JCheckBox cb : new ArrayList<>(trainList)) { 155 Train train = trainManager.getTrainById(cb.getName()); 156 if (cb.isSelected()) { 157 train.addTypeName((String) typeComboBox.getSelectedItem()); 158 } else { 159 train.deleteTypeName((String) typeComboBox.getSelectedItem()); 160 } 161 } 162 OperationsXml.save(); // save files 163 updateTrains(); 164 if (Setup.isCloseWindowOnSaveEnabled()) { 165 dispose(); 166 } 167 } 168 169 private void updateTrains() { 170 log.debug("update trains"); 171 removePropertyChangeTrains(); 172 trainList.clear(); 173 int x = 0; 174 pTrains.removeAll(); 175 String carType = (String) typeComboBox.getSelectedItem(); 176 if (copyCheckBox.isSelected()) { 177 carType = (String) copyComboBox.getSelectedItem(); 178 } 179 List<Train> trains = trainManager.getTrainsByNameList(); 180 for (Train train : trains) { 181 train.addPropertyChangeListener(this); 182 JCheckBox cb = new JCheckBox(train.getName()); 183 cb.setName(train.getId()); 184 cb.setToolTipText(Bundle.getMessage("TipTrainCarType", carType)); 185 addCheckBoxAction(cb); 186 trainList.add(cb); 187 cb.setSelected(train.isTypeNameAccepted(carType)); 188 addItemLeft(pTrains, cb, 0, x); 189 JLabel description = new JLabel(train.getDescription()); 190 addItemLeft(pTrains, description, 1, x++); 191 } 192 pTrains.revalidate(); 193 repaint(); 194 } 195 196 private void updateComboBox() { 197 log.debug("update combobox"); 198 InstanceManager.getDefault(CarTypes.class).updateComboBox(typeComboBox); 199 InstanceManager.getDefault(CarTypes.class).updateComboBox(copyComboBox); 200 } 201 202 private void selectCheckboxes(boolean b) { 203 for (JCheckBox checkBox : new ArrayList<>(trainList)) { 204 checkBox.setSelected(b); 205 } 206 } 207 208 @Override 209 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 210 // copy checkbox? 211 if (ae.getSource() == copyCheckBox) { 212 updateTrains(); 213 } else { 214 JCheckBox cb = (JCheckBox) ae.getSource(); 215 log.debug("Checkbox {} text: {}", cb.getName(), cb.getText()); 216 if (trainList.contains(cb)) { 217 log.debug("Checkbox train {}", cb.getText()); 218 } else { 219 log.error("Error checkbox not found"); 220 } 221 } 222 } 223 224 private void removePropertyChangeTrains() { 225 for (JCheckBox checkBox : new ArrayList<>(trainList)) { 226 // if object has been deleted, it's not here; ignore it 227 Train train = trainManager.getTrainById(checkBox.getName()); 228 if (train != null) { 229 train.removePropertyChangeListener(this); 230 } 231 } 232 } 233 234 @Override 235 public void dispose() { 236 trainManager.removePropertyChangeListener(this); 237 InstanceManager.getDefault(CarTypes.class).removePropertyChangeListener(this); 238 removePropertyChangeTrains(); 239 super.dispose(); 240 } 241 242 @Override 243 public void propertyChange(java.beans.PropertyChangeEvent e) { 244 log.debug("Property change {} old: {} new: {}", e.getPropertyName(), e.getOldValue(), e.getNewValue()); 245 if (e.getPropertyName().equals(TrainManager.LISTLENGTH_CHANGED_PROPERTY) || 246 e.getPropertyName().equals(Train.TYPES_CHANGED_PROPERTY) || 247 e.getPropertyName().equals(Train.NAME_CHANGED_PROPERTY) || 248 e.getPropertyName().equals(Train.DESCRIPTION_CHANGED_PROPERTY)) { 249 updateTrains(); 250 } 251 if (e.getPropertyName().equals(CarTypes.CARTYPES_CHANGED_PROPERTY) || 252 e.getPropertyName().equals(CarTypes.CARTYPES_NAME_CHANGED_PROPERTY)) { 253 updateComboBox(); 254 } 255 } 256 257 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrainsByCarTypeFrame.class); 258}