001package jmri.jmrit.operations.setup.gui; 002 003import java.awt.GridBagLayout; 004import java.time.LocalDate; 005import java.time.format.DateTimeFormatter; 006import java.time.format.DateTimeParseException; 007import java.util.Hashtable; 008 009import javax.swing.*; 010 011import org.slf4j.Logger; 012import org.slf4j.LoggerFactory; 013 014import jmri.InstanceManager; 015import jmri.jmrit.operations.setup.*; 016import jmri.jmrit.operations.trains.TrainManager; 017import jmri.jmrit.operations.trains.schedules.TrainScheduleManager; 018 019/** 020 * Panel for user edit of day to name mapping 021 * 022 * @author Dan Boudreau Copyright (C) 2026 023 */ 024public class EditDayToNameMapPanel extends OperationsPreferencesPanel { 025 026 // major buttons 027 JButton saveButton = new JButton(Bundle.getMessage("ButtonSave")); 028 JButton daysButton = new JButton(Bundle.getMessage("DaysOfWeek")); 029 JButton datesButton = new JButton(Bundle.getMessage("LoadDates")); 030 JButton resetButton = new JButton(Bundle.getMessage("Reset")); 031 032 protected Hashtable<Integer, JTextField> hashTableDayToName = new Hashtable<>(); 033 034 public EditDayToNameMapPanel() { 035 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 036 JPanel pDays = new JPanel(); 037 JScrollPane pManifestPane = new JScrollPane(pDays); 038 pManifestPane.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutDays"))); 039 pDays.setLayout(new BoxLayout(pDays, BoxLayout.Y_AXIS)); 040 041 for (int i = 0; i < Control.numberOfDays; i++) { 042 JPanel pDay = new JPanel(); 043 pDay.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BorderLayoutDay", i))); 044 JTextField textField = new JTextField(25); 045 pDay.add(textField); 046 pDays.add(pDay); 047 String name = Setup.getDayToName(Integer.toString(i)); 048 textField.setText(name); 049 hashTableDayToName.put(i, textField); 050 } 051 052 // row 11 053 JPanel pControl = new JPanel(); 054 pControl.setBorder(BorderFactory.createTitledBorder("")); 055 pControl.setLayout(new GridBagLayout()); 056 addItem(pControl, resetButton, 0, 0); 057 addItem(pControl, daysButton, 1, 0); 058 addItem(pControl, datesButton, 2, 0); 059 addItem(pControl, saveButton, 3, 0); 060 061 add(pManifestPane); 062 add(pControl); 063 064 // set up buttons 065 addButtonAction(resetButton); 066 addButtonAction(daysButton); 067 addButtonAction(datesButton); 068 addButtonAction(saveButton); 069 070 } 071 072 // Save buttons 073 @Override 074 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 075 if (ae.getSource() == resetButton) { 076 hashTableDayToName.forEach((key, textField) -> { 077 textField.setText(""); 078 }); 079 } 080 if (ae.getSource() == daysButton) { 081 loadDays(); 082 } 083 if (ae.getSource() == datesButton) { 084 loadDates(); 085 } 086 if (ae.getSource() == saveButton) { 087 savePreferences(); 088 var topLevelAncestor = getTopLevelAncestor(); 089 if (Setup.isCloseWindowOnSaveEnabled() && topLevelAncestor instanceof EditDayToNameMapFrame) { 090 ((EditDayToNameMapFrame) topLevelAncestor).dispose(); 091 } 092 } 093 } 094 095 private void loadDays() { 096 JTextField textField; 097 String[] days = InstanceManager.getDefault(TrainScheduleManager.class).getDaysOfWeek(); 098 int j = 0; 099 // list days starting with the day the user entered 100 textField = hashTableDayToName.get(0); 101 if (!textField.getText().isBlank()) { 102 for (String day : days) { 103 if (day.equals(textField.getText()) || j == days.length - 1) { 104 break; 105 } 106 j++; 107 } 108 } 109 for (int i = 0; i < Control.numberOfDays; i++) { 110 textField = hashTableDayToName.get(i); 111 textField.setText(days[j++]); 112 if (j == days.length) { 113 j = 0; 114 } 115 } 116 } 117 118 private void loadDates() { 119 JTextField textField; 120 // list dates starting with the date the user entered 121 textField = hashTableDayToName.get(0); 122 LocalDate ld = LocalDate.now(); 123 String year = Setup.getYearModeled(); 124 if (!year.isBlank()) { 125 // default format yyyy-MM-dd 126 try { 127 ld = LocalDate.parse(year + "-01-01"); 128 } catch (DateTimeParseException e) { 129 log.error("Year {} must be four digits", year); 130 } 131 } else { 132 year = "1956"; 133 } 134 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy"); 135 // three date formats accepted MMMM d, yyyy or MMMM d or MM/dd/yyyy 136 if (!textField.getText().isBlank()) { 137 // try month day year format MMMM d, yyyy 138 try { 139 ld = LocalDate.parse(textField.getText(), formatter); 140 } catch (DateTimeParseException e) { 141 // try month day format 142 try { 143 ld = LocalDate.parse(textField.getText() + ", " + year , formatter); 144 formatter = DateTimeFormatter.ofPattern("MMMM d"); 145 } catch (DateTimeParseException e2) { 146 // try MM/dd/yyyy 147 try { 148 formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); 149 ld = LocalDate.parse(textField.getText(), formatter); 150 } catch (DateTimeParseException e3) { 151 log.error("Couldn't covert {} to date", textField.getText()); 152 } 153 } 154 } 155 } 156 157 for (int i = 0; i < Control.numberOfDays; i++) { 158 textField = hashTableDayToName.get(i); 159 textField.setText(ld.format(formatter)); 160 ld = ld.plusDays(1); 161 } 162 } 163 164 @Override 165 public String getTabbedPreferencesTitle() { 166 return Bundle.getMessage("TitleDayToNameMap"); 167 } 168 169 @Override 170 public String getPreferencesTooltip() { 171 return null; 172 } 173 174 @Override 175 public void savePreferences() { 176 for (int i = 0; i < Control.numberOfDays; i++) { 177 JTextField textField = hashTableDayToName.get(i); 178 Setup.setDayToName(Integer.toString(i), textField.getText()); 179 } 180 InstanceManager.getDefault(OperationsSetupXml.class).writeOperationsFile(); 181 InstanceManager.getDefault(TrainManager.class).setTrainsModified(); 182 } 183 184 @Override 185 public boolean isDirty() { 186 return false; 187 } 188 189 private final static Logger log = LoggerFactory.getLogger(EditDayToNameMapPanel.class); 190}