001package jmri.jmrit.operations.locations.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.locations.*; 014import jmri.jmrit.operations.setup.Control; 015import jmri.jmrit.operations.setup.Setup; 016 017/** 018 * Frame to display and modify which locations have quick service tracks 019 * 020 * @author Dan Boudreau Copyright (C) 2026 021 */ 022public class LocationsByQuickServiceFrame extends OperationsFrame implements java.beans.PropertyChangeListener { 023 024 LocationManager locationManager = InstanceManager.getDefault(LocationManager.class); 025 026 // checkboxes have the location id or track id as the checkbox name 027 ArrayList<JCheckBox> locationCheckBoxList = new ArrayList<>(); 028 ArrayList<JCheckBox> trackCheckBoxList = new ArrayList<>(); 029 JPanel locationCheckBoxes = new JPanel(); 030 031 // panels 032 JPanel pLocations; 033 034 // major buttons 035 JButton clearButton = new JButton(Bundle.getMessage("ClearAll")); 036 JButton setButton = new JButton(Bundle.getMessage("SelectAll")); 037 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 038 039 // selected location 040 Location _location; 041 042 public LocationsByQuickServiceFrame() { 043 super(); 044 } 045 046 public void initComponents(Location location) { 047 this._location = location; 048 initComponents(); 049 } 050 051 @Override 052 public void initComponents() { 053 054 // general GUI config 055 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 056 057 // Set up the panels 058 JPanel pCarType = new JPanel(); 059 pCarType.setLayout(new GridBagLayout()); 060 pCarType.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Type"))); 061 062 pLocations = new JPanel(); 063 pLocations.setLayout(new GridBagLayout()); 064 JScrollPane locationPane = new JScrollPane(pLocations); 065 locationPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 066 locationPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("Locations"))); 067 updateLocations(); 068 069 JPanel pButtons = new JPanel(); 070 pButtons.setLayout(new GridBagLayout()); 071 pButtons.setBorder(BorderFactory.createTitledBorder("")); 072 073 addItem(pButtons, clearButton, 0, 0); 074 addItem(pButtons, setButton, 1, 0); 075 addItem(pButtons, saveButton, 2, 0); 076 077 getContentPane().add(pCarType); 078 getContentPane().add(locationPane); 079 getContentPane().add(pButtons); 080 081 // setup buttons 082 addButtonAction(setButton); 083 addButtonAction(clearButton); 084 addButtonAction(saveButton); 085 086 locationManager.addPropertyChangeListener(this); 087 088 // build menu 089 addHelpMenu("package.jmri.jmrit.operations.Operations_ModifyLocationsByQuickService", true); // NOI18N 090 091 if (_location != null) { 092 setTitle(Bundle.getMessage("TitleModifyLocQuickService")); 093 } else { 094 setTitle(Bundle.getMessage("TitleModifyLocsQuickService")); 095 } 096 097 setPreferredSize(null); // we need to resize this frame 098 initMinimumSize(new Dimension(Control.panelWidth400, Control.panelHeight250)); 099 setSize(getWidth() + 25, getHeight()); // make a bit wider to eliminate scroll bar 100 } 101 102 @Override 103 public void checkBoxActionPerformed(java.awt.event.ActionEvent ae) { 104 JCheckBox cb = (JCheckBox) ae.getSource(); 105 log.debug("Checkbox {} text: {}", cb.getName(), cb.getText()); 106 if (locationCheckBoxList.contains(cb)) { 107 log.debug("Checkbox location {}", cb.getText()); 108 // update all tracks at location{ 109 String locId = cb.getName(); 110 for (JCheckBox cbt : new ArrayList<>(trackCheckBoxList)) { 111 String[] id = cbt.getName().split(Location.LOC_TRACK_REGIX); 112 if (locId.equals(id[0])) { 113 cbt.setSelected(cb.isSelected()); 114 } 115 } 116 } 117 } 118 119 // Save, Delete, Add 120 @Override 121 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 122 if (ae.getSource() == saveButton) { 123 save(); 124 } 125 if (ae.getSource() == setButton) { 126 selectCheckboxes(true); 127 } 128 if (ae.getSource() == clearButton) { 129 selectCheckboxes(false); 130 } 131 } 132 133 /** 134 * Update the car types that locations and tracks service. Note that the 135 * checkbox name is the id of the location or track. 136 */ 137 private void save() { 138 log.debug("save {} locations", locationCheckBoxList.size()); 139 removePropertyChangeLocations(); 140 for (JCheckBox cb : new ArrayList<>(locationCheckBoxList)) { 141 Location loc = locationManager.getLocationById(cb.getName()); 142 // save tracks that have the same id as the location 143 for (JCheckBox cbt : new ArrayList<>(trackCheckBoxList)) { 144 String[] id = cbt.getName().split(Location.LOC_TRACK_REGIX); 145 if (loc.getId().equals(id[0])) { 146 Track track = loc.getTrackById(cbt.getName()); 147 track.setQuickServiceEnabled(cb.isSelected() && cbt.isSelected()); 148 } 149 } 150 } 151 OperationsXml.save(); 152 updateLocations(); 153 if (Setup.isCloseWindowOnSaveEnabled()) { 154 dispose(); 155 } 156 } 157 158 private void updateLocations() { 159 log.debug("update checkboxes"); 160 removePropertyChangeLocations(); 161 locationCheckBoxList.clear(); 162 trackCheckBoxList.clear(); 163 int x = 0; 164 pLocations.removeAll(); 165 // did the location get deleted? 166 if (_location != null && locationManager.getLocationByName(_location.getName()) == null) { 167 _location = null; 168 } 169 List<Location> locations = locationManager.getLocationsByNameList(); 170 for (Location loc : locations) { 171 // show only one location? 172 if (_location != null && _location != loc) { 173 continue; 174 } 175 loc.addPropertyChangeListener(this); 176 JCheckBox cb = new JCheckBox(loc.getName()); 177 cb.setName(loc.getId()); 178 addCheckBoxAction(cb); 179 locationCheckBoxList.add(cb); 180 addItemLeft(pLocations, cb, 0, x++); 181 cb.setSelected(loc.hasQuickService()); 182 List<Track> tracks = loc.getTracksByNameList(null); 183 for (Track track : tracks) { 184 track.addPropertyChangeListener(this); 185 JCheckBox cbt = new JCheckBox(track.getName()); 186 cbt.setName(track.getId()); 187 trackCheckBoxList.add(cbt); 188 cbt.setSelected(track.isQuickServiceEnabled()); 189 addItemLeft(pLocations, cbt, 1, x++); 190 } 191 } 192 pLocations.revalidate(); 193 repaint(); 194 } 195 196 private void selectCheckboxes(boolean select) { 197 for (JCheckBox cb : new ArrayList<>(locationCheckBoxList)) { 198 cb.setSelected(select); 199 } 200 for (JCheckBox cb : new ArrayList<>(trackCheckBoxList)) { 201 cb.setSelected(select); 202 } 203 } 204 205 private void removePropertyChangeLocations() { 206 for (JCheckBox cb : new ArrayList<>(locationCheckBoxList)) { 207 // checkbox name is the location id 208 Location loc = locationManager.getLocationById(cb.getName()); 209 if (loc != null) { 210 loc.removePropertyChangeListener(this); 211 List<Track> tracks = loc.getTracksList(); 212 for (Track track : tracks) { 213 track.removePropertyChangeListener(this); 214 } 215 } 216 } 217 } 218 219 @Override 220 public void dispose() { 221 locationManager.removePropertyChangeListener(this); 222 removePropertyChangeLocations(); 223 super.dispose(); 224 } 225 226 @Override 227 public void propertyChange(java.beans.PropertyChangeEvent e) { 228 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 229 .getNewValue()); 230 if (e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY) || 231 e.getPropertyName().equals(Location.NAME_CHANGED_PROPERTY) || 232 e.getPropertyName().equals(Location.TRACK_LISTLENGTH_CHANGED_PROPERTY) || 233 e.getPropertyName().equals(Track.LOAD_OPTIONS_CHANGED_PROPERTY) || 234 e.getPropertyName().equals(Track.NAME_CHANGED_PROPERTY)) { 235 updateLocations(); 236 } 237 } 238 239 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LocationsByQuickServiceFrame.class); 240}