001package jmri.jmrit.operations.trains.schedules; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import java.util.List; 006import javax.swing.JTable; 007import jmri.InstanceManager; 008import jmri.jmrit.beantable.EnablingCheckboxRenderer; 009import jmri.jmrit.operations.setup.Control; 010import jmri.jmrit.operations.trains.Train; 011import jmri.jmrit.operations.trains.TrainManager; 012import jmri.util.swing.XTableColumnModel; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016/** 017 * Table Model for edit of train schedules used by operations 018 * 019 * @author Daniel Boudreau Copyright (C) 2010, 2012 020 */ 021public class TrainsScheduleTableModel extends javax.swing.table.AbstractTableModel implements PropertyChangeListener { 022 023 TrainManager trainManager = InstanceManager.getDefault(TrainManager.class); 024 TrainScheduleManager scheduleManager = InstanceManager.getDefault(TrainScheduleManager.class); 025 026 // Defines the columns 027 private static final int IDCOLUMN = 0; 028 private static final int NAMECOLUMN = IDCOLUMN + 1; 029 private static final int DESCRIPTIONCOLUMN = NAMECOLUMN + 1; 030 031 private static final int FIXEDCOLUMN = DESCRIPTIONCOLUMN + 1; 032 033 public TrainsScheduleTableModel() { 034 super(); 035 trainManager.addPropertyChangeListener(this); 036 scheduleManager.addPropertyChangeListener(this); 037 updateList(); 038 addPropertyChangeTrainSchedules(); 039 } 040 041 public final int SORTBYNAME = 1; 042 public final int SORTBYTIME = 2; 043 public final int SORTBYDEPARTS = 3; 044 public final int SORTBYTERMINATES = 4; 045 public final int SORTBYROUTE = 5; 046 public final int SORTBYID = 6; 047 048 private int _sort = SORTBYTIME; 049 050 public void setSort(int sort) { 051 _sort = sort; 052 updateList(); 053 //fireTableStructureChanged(); 054 initTable(); 055 if (_table.getRowSorter() != null) { 056 _table.getRowSorter().setSortKeys(null); 057 } 058 } 059 060 private void updateList() { 061 // first, remove listeners from the individual objects 062 removePropertyChangeTrains(); 063 064 if (_sort == SORTBYID) { 065 sysList = trainManager.getTrainsByIdList(); 066 } else if (_sort == SORTBYNAME) { 067 sysList = trainManager.getTrainsByNameList(); 068 } else if (_sort == SORTBYTIME) { 069 sysList = trainManager.getTrainsByTimeList(); 070 } else if (_sort == SORTBYDEPARTS) { 071 sysList = trainManager.getTrainsByDepartureList(); 072 } else if (_sort == SORTBYTERMINATES) { 073 sysList = trainManager.getTrainsByTerminatesList(); 074 } else if (_sort == SORTBYROUTE) { 075 sysList = trainManager.getTrainsByRouteList(); 076 } 077 078 // and add listeners back in 079 addPropertyChangeTrains(); 080 } 081 082 public List<Train> getSelectedTrainList() { 083 return sysList; 084 } 085 086 List<Train> sysList = null; 087 JTable _table = null; 088 TrainsScheduleTableFrame _frame = null; 089 090 void initTable(JTable table, TrainsScheduleTableFrame frame) { 091 _table = table; 092 _frame = frame; 093 initTable(); 094 } 095 096 // only the first three columns of the table have defaults 097 private final int[] tableScheduleColumnWidths = {50, 70, 120}; 098 099 void initTable() { 100 if (_table == null) { 101 return; 102 } 103 104 // Save table column order 105 XTableColumnModel tcm = new XTableColumnModel(); 106 _table.setColumnModel(tcm); 107 _table.createDefaultColumnsFromModel(); 108 109 // Install the button handlers 110 _table.setDefaultRenderer(Boolean.class, new EnablingCheckboxRenderer()); 111 112 // set column preferred widths 113 for (int i = 0; i < tableScheduleColumnWidths.length; i++) { 114 tcm.getColumn(i).setPreferredWidth(tableScheduleColumnWidths[i]); 115 } 116 _frame.loadTableDetails(_table); 117 } 118 119 @Override 120 public int getRowCount() { 121 return sysList.size(); 122 } 123 124 public int getFixedColumn() { 125 return FIXEDCOLUMN; 126 } 127 128 @Override 129 public int getColumnCount() { 130 return getFixedColumn() + scheduleManager.numEntries(); 131 } 132 133 @Override 134 public String getColumnName(int col) { 135 switch (col) { 136 case IDCOLUMN: 137 if (_sort == SORTBYID) { 138 return Bundle.getMessage("Id"); 139 } 140 return Bundle.getMessage("Time"); 141 case NAMECOLUMN: 142 return Bundle.getMessage("Name"); 143 case DESCRIPTIONCOLUMN: 144 return Bundle.getMessage("Description"); 145 default: 146 // fall out 147 break; 148 } 149 TrainSchedule ts = getSchedule(col); 150 if (ts != null) { 151 return ts.getName(); 152 } 153 return "unknown"; // NOI18N 154 } 155 156 @Override 157 public Class<?> getColumnClass(int col) { 158 switch (col) { 159 case IDCOLUMN: 160 return String.class; 161 case NAMECOLUMN: 162 return String.class; 163 case DESCRIPTIONCOLUMN: 164 return String.class; 165 default: 166 // fall out 167 break; 168 } 169 if (col >= getFixedColumn() && col < getColumnCount()) { 170 return Boolean.class; 171 } 172 return null; 173 } 174 175 @Override 176 public boolean isCellEditable(int row, int col) { 177 switch (col) { 178 case IDCOLUMN: 179 case NAMECOLUMN: 180 case DESCRIPTIONCOLUMN: 181 return false; 182 default: 183 return true; 184 } 185 } 186 187 @Override 188 public Object getValueAt(int row, int col) { 189 if (row >= getRowCount()) { 190 return "ERROR row " + row; // NOI18N 191 } 192 Train train = sysList.get(row); 193 if (train == null) { 194 return "ERROR train unknown " + row; // NOI18N 195 } 196 switch (col) { 197 case IDCOLUMN: { 198 if (_sort == SORTBYID) { 199 return train.getId(); 200 } 201 return train.getDepartureTime(); 202 } 203 case NAMECOLUMN: 204 return train.getIconName(); 205 case DESCRIPTIONCOLUMN: 206 return train.getDescription(); 207 default: 208 // fall out 209 break; 210 } 211 TrainSchedule ts = getSchedule(col); 212 if (ts != null) { 213 return ts.containsTrainId(train.getId()); 214 } 215 return "unknown " + col; // NOI18N 216 } 217 218 @Override 219 public void setValueAt(Object value, int row, int col) { 220 TrainSchedule ts = getSchedule(col); 221 if (ts != null) { 222 Train train = sysList.get(row); 223 if (train == null) { 224 log.error("train not found"); 225 return; 226 } 227 if (((Boolean) value).booleanValue()) { 228 ts.addTrainId(train.getId()); 229 } else { 230 ts.removeTrainId(train.getId()); 231 } 232 } 233 } 234 235 @Override 236 public void propertyChange(PropertyChangeEvent e) { 237 if (Control.SHOW_PROPERTY) { 238 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 239 .getNewValue()); 240 } 241 if (e.getPropertyName().equals(TrainManager.LISTLENGTH_CHANGED_PROPERTY) || 242 e.getPropertyName().equals(TrainManager.TRAIN_ACTION_CHANGED_PROPERTY)) { 243 updateList(); 244 fireTableDataChanged(); 245 } else if (e.getPropertyName().equals(TrainScheduleManager.LISTLENGTH_CHANGED_PROPERTY) || 246 e.getPropertyName().equals(TrainSchedule.NAME_CHANGED_PROPERTY)) { 247 // update property change 248 removePropertyChangeTrainSchedules(); 249 addPropertyChangeTrainSchedules(); 250 //fireTableStructureChanged(); 251 initTable(); 252 } else if (e.getPropertyName().equals(TrainSchedule.SCHEDULE_CHANGED_PROPERTY)) { 253 fireTableDataChanged(); 254 } else if (e.getSource().getClass().equals(Train.class)) { 255 Train train = (Train) e.getSource(); 256 int row = sysList.indexOf(train); 257 if (Control.SHOW_PROPERTY) { 258 log.debug("Update train table row: {} name: {}", row, train.getName()); 259 } 260 if (row >= 0) { 261 fireTableRowsUpdated(row, row); 262 } 263 } 264 } 265 266 public TrainSchedule getSchedule(int col) { 267 if (col >= getFixedColumn() && col < getColumnCount()) { 268 List<TrainSchedule> trainSchedules = scheduleManager.getSchedulesByIdList(); 269 TrainSchedule ts = trainSchedules.get(col - getFixedColumn()); 270 return ts; 271 } 272 return null; 273 } 274 275 private void removePropertyChangeTrainSchedules() { 276 List<TrainSchedule> trainSchedules = scheduleManager.getSchedulesByIdList(); 277 for (TrainSchedule ts : trainSchedules) { 278 ts.removePropertyChangeListener(this); 279 } 280 } 281 282 private void addPropertyChangeTrainSchedules() { 283 List<TrainSchedule> trainSchedules = scheduleManager.getSchedulesByIdList(); 284 for (TrainSchedule ts : trainSchedules) { 285 ts.addPropertyChangeListener(this); 286 } 287 } 288 289 private void removePropertyChangeTrains() { 290 if (sysList != null) { 291 for (Train train : sysList) { 292 train.removePropertyChangeListener(this); 293 } 294 } 295 } 296 297 private void addPropertyChangeTrains() { 298 if (sysList != null) { 299 for (Train train : sysList) { 300 train.addPropertyChangeListener(this); 301 } 302 } 303 } 304 305 public void dispose() { 306 trainManager.removePropertyChangeListener(this); 307 scheduleManager.removePropertyChangeListener(this); 308 removePropertyChangeTrains(); 309 removePropertyChangeTrainSchedules(); 310 } 311 312 private final static Logger log = LoggerFactory.getLogger(TrainsScheduleTableModel.class); 313}