001package jmri.jmrit.operations.routes.gui; 002 003import java.awt.BorderLayout; 004import java.awt.FlowLayout; 005import java.awt.event.ActionEvent; 006import java.awt.event.ActionListener; 007import java.beans.PropertyChangeEvent; 008import java.beans.PropertyChangeListener; 009import java.util.ArrayList; 010import java.util.List; 011 012import javax.swing.*; 013import javax.swing.colorchooser.AbstractColorChooserPanel; 014import javax.swing.table.DefaultTableCellRenderer; 015import javax.swing.table.TableCellEditor; 016 017import jmri.jmrit.operations.routes.Route; 018import jmri.jmrit.operations.routes.RouteLocation; 019import jmri.jmrit.operations.setup.Control; 020import jmri.jmrit.operations.setup.Setup; 021import jmri.jmrit.symbolicprog.ValueEditor; 022import jmri.jmrit.symbolicprog.ValueRenderer; 023import jmri.util.swing.*; 024import jmri.util.table.ButtonEditor; 025import jmri.util.table.ButtonRenderer; 026 027/** 028 * Table Model for edit of route locations used by operations 029 * 030 * @author Daniel Boudreau Copyright (C) 2008, 2013, 2025 031 */ 032public class RouteEditTableModel extends javax.swing.table.AbstractTableModel implements PropertyChangeListener { 033 034 // Defines the columns 035 private static final int ID_COLUMN = 0; 036 private static final int NAME_COLUMN = ID_COLUMN + 1; 037 private static final int TRAIN_DIRECTION_COLUMN = NAME_COLUMN + 1; 038 private static final int MAXMOVES_COLUMN = TRAIN_DIRECTION_COLUMN + 1; 039 private static final int RANDOM_CONTROL_COLUMN = MAXMOVES_COLUMN + 1; 040 private static final int PICKUP_COLUMN = RANDOM_CONTROL_COLUMN + 1; 041 private static final int DROP_COLUMN = PICKUP_COLUMN + 1; 042 private static final int LOCAL_COLUMN = DROP_COLUMN + 1; 043 private static final int DEPARTURE_TIME_COLUMN = LOCAL_COLUMN + 1; 044 private static final int TRAVEL_COLUMN = DEPARTURE_TIME_COLUMN + 1; 045 private static final int MAXLENGTH_COLUMN = TRAVEL_COLUMN + 1; 046 private static final int GRADE_COLUMN = MAXLENGTH_COLUMN + 1; 047 private static final int TRAINICONX_COLUMN = GRADE_COLUMN + 1; 048 private static final int TRAINICONY_COLUMN = TRAINICONX_COLUMN + 1; 049 private static final int COMMENT_COLUMN = TRAINICONY_COLUMN + 1; 050 private static final int UP_COLUMN = COMMENT_COLUMN + 1; 051 private static final int DOWN_COLUMN = UP_COLUMN + 1; 052 private static final int DELETE_COLUMN = DOWN_COLUMN + 1; 053 054 private static final int HIGHEST_COLUMN = DELETE_COLUMN + 1; 055 056 private JTable _table; 057 private Route _route; 058 private RouteEditFrame _frame; 059 List<RouteLocation> _routeList = new ArrayList<>(); 060 061 public RouteEditTableModel() { 062 super(); 063 } 064 065 private void updateList() { 066 if (_route == null) { 067 return; 068 } 069 // first, remove listeners from the individual objects 070 removePropertyChangeRouteLocations(); 071 _routeList = _route.getLocationsBySequenceList(); 072 // and add them back in 073 for (RouteLocation rl : _routeList) { 074 rl.addPropertyChangeListener(this); 075 } 076 } 077 078 protected void initTable(RouteEditFrame frame, JTable table, Route route) { 079 _frame = frame; 080 _table = table; 081 _route = route; 082 if (_route != null) { 083 _route.addPropertyChangeListener(this); 084 } 085 Setup.getDefault().addPropertyChangeListener(this); 086 initTable(table); 087 } 088 089 private void initTable(JTable table) { 090 // Use XTableColumnModel so we can control which columns are visible 091 XTableColumnModel tcm = new XTableColumnModel(); 092 _table.setColumnModel(tcm); 093 _table.createDefaultColumnsFromModel(); 094 // Install the button handlers 095 ButtonRenderer buttonRenderer = new ButtonRenderer(); 096 TableCellEditor buttonEditor = new ButtonEditor(new JButton()); 097 tcm.getColumn(COMMENT_COLUMN).setCellRenderer(buttonRenderer); 098 tcm.getColumn(COMMENT_COLUMN).setCellEditor(buttonEditor); 099 tcm.getColumn(UP_COLUMN).setCellRenderer(buttonRenderer); 100 tcm.getColumn(UP_COLUMN).setCellEditor(buttonEditor); 101 tcm.getColumn(DOWN_COLUMN).setCellRenderer(buttonRenderer); 102 tcm.getColumn(DOWN_COLUMN).setCellEditor(buttonEditor); 103 tcm.getColumn(DELETE_COLUMN).setCellRenderer(buttonRenderer); 104 tcm.getColumn(DELETE_COLUMN).setCellEditor(buttonEditor); 105 106 // for tool tips 107 DefaultTableCellRenderer defaultRenderer = new DefaultTableCellRenderer(); 108 tcm.getColumn(NAME_COLUMN).setCellRenderer(defaultRenderer); 109 tcm.getColumn(MAXMOVES_COLUMN).setCellRenderer(defaultRenderer); 110 tcm.getColumn(TRAVEL_COLUMN).setCellRenderer(defaultRenderer); 111 tcm.getColumn(MAXLENGTH_COLUMN).setCellRenderer(defaultRenderer); 112 tcm.getColumn(GRADE_COLUMN).setCellRenderer(defaultRenderer); 113 114 table.setDefaultRenderer(JComboBox.class, new ValueRenderer()); 115 table.setDefaultEditor(JComboBox.class, new ValueEditor()); 116 117 // set column preferred widths 118 table.getColumnModel().getColumn(ID_COLUMN).setPreferredWidth(40); 119 table.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(150); 120 table.getColumnModel().getColumn(TRAIN_DIRECTION_COLUMN).setPreferredWidth(95); 121 table.getColumnModel().getColumn(MAXMOVES_COLUMN).setPreferredWidth(50); 122 table.getColumnModel().getColumn(RANDOM_CONTROL_COLUMN).setPreferredWidth(65); 123 table.getColumnModel().getColumn(PICKUP_COLUMN).setPreferredWidth(65); 124 table.getColumnModel().getColumn(DROP_COLUMN).setPreferredWidth(65); 125 table.getColumnModel().getColumn(LOCAL_COLUMN).setPreferredWidth(75); 126 table.getColumnModel().getColumn(TRAVEL_COLUMN).setPreferredWidth(65); 127 table.getColumnModel().getColumn(DEPARTURE_TIME_COLUMN).setPreferredWidth(65); 128 table.getColumnModel().getColumn(MAXLENGTH_COLUMN).setPreferredWidth(75); 129 table.getColumnModel().getColumn(GRADE_COLUMN).setPreferredWidth(50); 130 table.getColumnModel().getColumn(TRAINICONX_COLUMN).setPreferredWidth(35); 131 table.getColumnModel().getColumn(TRAINICONY_COLUMN).setPreferredWidth(35); 132 table.getColumnModel().getColumn(COMMENT_COLUMN).setPreferredWidth(70); 133 table.getColumnModel().getColumn(UP_COLUMN).setPreferredWidth(60); 134 table.getColumnModel().getColumn(DOWN_COLUMN).setPreferredWidth(70); 135 table.getColumnModel().getColumn(DELETE_COLUMN).setPreferredWidth(80); 136 137 _frame.loadTableDetails(table); 138 // does not use a table sorter 139 table.setRowSorter(null); 140 141 // turn on column that on earlier versions was off 142 tcm.setColumnVisible(tcm.getColumnByModelIndex(DEPARTURE_TIME_COLUMN), true); 143 144 updateList(); 145 } 146 147 @Override 148 public int getRowCount() { 149 return _routeList.size(); 150 } 151 152 @Override 153 public int getColumnCount() { 154 return HIGHEST_COLUMN; 155 } 156 157 @Override 158 public String getColumnName(int col) { 159 switch (col) { 160 case ID_COLUMN: 161 return Bundle.getMessage("Id"); 162 case NAME_COLUMN: 163 return Bundle.getMessage("Location"); 164 case TRAIN_DIRECTION_COLUMN: 165 return Bundle.getMessage("TrainDirection"); 166 case MAXMOVES_COLUMN: 167 return Bundle.getMessage("MaxMoves"); 168 case RANDOM_CONTROL_COLUMN: 169 return Bundle.getMessage("Random"); 170 case PICKUP_COLUMN: 171 return Bundle.getMessage("Pickups"); 172 case DROP_COLUMN: 173 return Bundle.getMessage("Drops"); 174 case LOCAL_COLUMN: 175 return Bundle.getMessage("LocalMoves"); 176 case TRAVEL_COLUMN: 177 return Bundle.getMessage("Travel"); 178 case DEPARTURE_TIME_COLUMN: 179 return Bundle.getMessage("Time"); 180 case MAXLENGTH_COLUMN: 181 return Bundle.getMessage("MaxLength"); 182 case GRADE_COLUMN: 183 return Bundle.getMessage("Grade"); 184 case TRAINICONX_COLUMN: 185 return Bundle.getMessage("X"); 186 case TRAINICONY_COLUMN: 187 return Bundle.getMessage("Y"); 188 case COMMENT_COLUMN: 189 return Bundle.getMessage("Comment"); 190 case UP_COLUMN: 191 return Bundle.getMessage("Up"); 192 case DOWN_COLUMN: 193 return Bundle.getMessage("Down"); 194 case DELETE_COLUMN: 195 return Bundle.getMessage("ButtonDelete"); // titles above all columns 196 default: 197 return "unknown"; // NOI18N 198 } 199 } 200 201 @Override 202 public Class<?> getColumnClass(int col) { 203 switch (col) { 204 case ID_COLUMN: 205 case NAME_COLUMN: 206 return String.class; 207 case TRAVEL_COLUMN: 208 case MAXLENGTH_COLUMN: 209 case MAXMOVES_COLUMN: 210 case TRAINICONX_COLUMN: 211 case TRAINICONY_COLUMN: 212 return Integer.class; 213 case GRADE_COLUMN: 214 return Double.class; 215 case TRAIN_DIRECTION_COLUMN: 216 case RANDOM_CONTROL_COLUMN: 217 case PICKUP_COLUMN: 218 case DROP_COLUMN: 219 case LOCAL_COLUMN: 220 case DEPARTURE_TIME_COLUMN: 221 return JComboBox.class; 222 case COMMENT_COLUMN: 223 case UP_COLUMN: 224 case DOWN_COLUMN: 225 case DELETE_COLUMN: 226 return JButton.class; 227 default: 228 return null; 229 } 230 } 231 232 @Override 233 public boolean isCellEditable(int row, int col) { 234 switch (col) { 235 case DELETE_COLUMN: 236 case TRAIN_DIRECTION_COLUMN: 237 case MAXMOVES_COLUMN: 238 case RANDOM_CONTROL_COLUMN: 239 case PICKUP_COLUMN: 240 case DROP_COLUMN: 241 case LOCAL_COLUMN: 242 case TRAVEL_COLUMN: 243 case DEPARTURE_TIME_COLUMN: 244 case MAXLENGTH_COLUMN: 245 case GRADE_COLUMN: 246 case TRAINICONX_COLUMN: 247 case TRAINICONY_COLUMN: 248 case COMMENT_COLUMN: 249 case UP_COLUMN: 250 case DOWN_COLUMN: 251 return true; 252 default: 253 return false; 254 } 255 } 256 257 @Override 258 public Object getValueAt(int row, int col) { 259 if (row >= getRowCount()) { 260 return "ERROR unknown " + row; // NOI18N 261 } 262 RouteLocation rl = _routeList.get(row); 263 if (rl == null) { 264 return "ERROR unknown route location " + row; // NOI18N 265 } 266 switch (col) { 267 case ID_COLUMN: 268 return rl.getId(); 269 case NAME_COLUMN: 270 setLocationToolTip(rl); 271 return rl.getName(); 272 case TRAIN_DIRECTION_COLUMN: { 273 JComboBox<String> cb = Setup.getTrainDirectionComboBox(); 274 cb.setSelectedItem(rl.getTrainDirectionString()); 275 return cb; 276 } 277 case MAXMOVES_COLUMN: 278 setToolTip(Bundle.getMessage("TipColMaxMoves", rl.getName()), col); 279 return rl.getMaxCarMoves(); 280 case RANDOM_CONTROL_COLUMN: { 281 JComboBox<String> cb = getRandomControlComboBox(); 282 cb.setToolTipText(Bundle.getMessage("TipRandomReduce", rl.getRandomControl())); 283 cb.setSelectedItem(rl.getRandomControl()); 284 return cb; 285 } 286 case PICKUP_COLUMN: { 287 JComboBox<String> cb = getYesNoComboBox(); 288 cb.setSelectedItem(rl.isPickUpAllowed() ? Bundle.getMessage("yes") : Bundle.getMessage("no")); 289 return cb; 290 } 291 case DROP_COLUMN: { 292 JComboBox<String> cb = getYesNoComboBox(); 293 cb.setSelectedItem(rl.isDropAllowed() ? Bundle.getMessage("yes") : Bundle.getMessage("no")); 294 return cb; 295 } 296 case LOCAL_COLUMN: { 297 JComboBox<String> cb = getYesNoComboBox(); 298 cb.setSelectedItem(rl.isLocalMovesAllowed() ? Bundle.getMessage("yes") : Bundle.getMessage("no")); 299 return cb; 300 } 301 case TRAVEL_COLUMN: { 302 setToolTip(Bundle.getMessage("TipColTravelTime"), col); 303 return rl.getWait() + Setup.getTravelTime(); 304 } 305 case DEPARTURE_TIME_COLUMN: { 306 JComboBox<String> cb = getTimeComboBox(); 307 cb.setToolTipText(Bundle.getMessage("TipDepartureTime", rl.getName())); 308 cb.setSelectedItem(rl.getDepartureTime()); 309 return cb; 310 } 311 case MAXLENGTH_COLUMN: 312 setToolTip(Bundle.getMessage("TipColMaxLength", rl.getName(), Setup.getLengthUnit().toLowerCase()), col); 313 return rl.getMaxTrainLength(); 314 case GRADE_COLUMN: 315 setToolTip(Bundle.getMessage("TipColGrade", rl.getName()), col); 316 return rl.getGrade(); 317 case TRAINICONX_COLUMN: 318 return rl.getTrainIconX(); 319 case TRAINICONY_COLUMN: 320 return rl.getTrainIconY(); 321 case COMMENT_COLUMN: { 322 if (rl.getComment().equals(RouteLocation.NONE)) { 323 return Bundle.getMessage("Add"); 324 } else { 325 return Bundle.getMessage("ButtonEdit"); 326 } 327 } 328 case UP_COLUMN: 329 return Bundle.getMessage("Up"); 330 case DOWN_COLUMN: 331 return Bundle.getMessage("Down"); 332 case DELETE_COLUMN: 333 return Bundle.getMessage("ButtonDelete"); 334 default: 335 return "unknown " + col; // NOI18N 336 } 337 } 338 339 @Override 340 public void setValueAt(Object value, int row, int col) { 341 if (value == null) { 342 log.debug("Warning route table row {} still in edit", row); 343 return; 344 } 345 RouteLocation rl = _routeList.get(row); 346 if (rl == null) { 347 log.error("ERROR unknown route location for row: {}", row); // NOI18N 348 } 349 switch (col) { 350 case COMMENT_COLUMN: 351 setComment(rl); 352 break; 353 case UP_COLUMN: 354 moveUpRouteLocation(rl); 355 break; 356 case DOWN_COLUMN: 357 moveDownRouteLocation(rl); 358 break; 359 case DELETE_COLUMN: 360 deleteRouteLocation(rl); 361 break; 362 case TRAIN_DIRECTION_COLUMN: 363 setTrainDirection(value, rl); 364 break; 365 case MAXMOVES_COLUMN: 366 setMaxTrainMoves(value, rl); 367 break; 368 case RANDOM_CONTROL_COLUMN: 369 setRandomControlValue(value, rl); 370 break; 371 case PICKUP_COLUMN: 372 setPickup(value, rl); 373 break; 374 case DROP_COLUMN: 375 setDrop(value, rl); 376 break; 377 case LOCAL_COLUMN: 378 setLocal(value, rl); 379 break; 380 case TRAVEL_COLUMN: 381 setTravel(value, rl); 382 break; 383 case DEPARTURE_TIME_COLUMN: 384 setDepartureTime(value, rl); 385 break; 386 case MAXLENGTH_COLUMN: 387 setMaxTrainLength(value, rl); 388 break; 389 case GRADE_COLUMN: 390 setGrade(value, rl); 391 break; 392 case TRAINICONX_COLUMN: 393 setTrainIconX(value, rl); 394 break; 395 case TRAINICONY_COLUMN: 396 setTrainIconY(value, rl); 397 break; 398 default: 399 break; 400 } 401 } 402 403 private void moveUpRouteLocation(RouteLocation rl) { 404 log.debug("move location up"); 405 _route.moveLocationUp(rl); 406 } 407 408 private void moveDownRouteLocation(RouteLocation rl) { 409 log.debug("move location down"); 410 _route.moveLocationDown(rl); 411 } 412 413 private void deleteRouteLocation(RouteLocation rl) { 414 log.debug("Delete location"); 415 _route.deleteLocation(rl); 416 } 417 418 private int _trainDirection = Setup.getDirectionInt(Setup.getTrainDirectionList().get(0)); 419 420 public int getLastTrainDirection() { 421 return _trainDirection; 422 } 423 424 private void setTrainDirection(Object value, RouteLocation rl) { 425 _trainDirection = Setup.getDirectionInt((String) ((JComboBox<?>) value).getSelectedItem()); 426 rl.setTrainDirection(_trainDirection); 427 // update train icon 428 rl.setTrainIconCoordinates(); 429 } 430 431 private int _maxTrainMoves = Setup.getCarMoves(); 432 433 public int getLastMaxTrainMoves() { 434 return _maxTrainMoves; 435 } 436 437 private void setMaxTrainMoves(Object value, RouteLocation rl) { 438 int moves = (int) value; 439 if (moves <= 500) { 440 rl.setMaxCarMoves(moves); 441 _maxTrainMoves = moves; 442 } else { 443 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("MaximumLocationMoves"), Bundle 444 .getMessage("CanNotChangeMoves"), JmriJOptionPane.ERROR_MESSAGE); 445 } 446 } 447 448 private void setRandomControlValue(Object value, RouteLocation rl) { 449 rl.setRandomControl((String) ((JComboBox<?>) value).getSelectedItem()); 450 } 451 452 private void setDrop(Object value, RouteLocation rl) { 453 rl.setDropAllowed( 454 ((String) ((JComboBox<?>) value).getSelectedItem()).equals(Bundle.getMessage("yes"))); 455 } 456 457 private void setPickup(Object value, RouteLocation rl) { 458 rl.setPickUpAllowed( 459 ((String) ((JComboBox<?>) value).getSelectedItem()).equals(Bundle.getMessage("yes"))); 460 } 461 462 private void setLocal(Object value, RouteLocation rl) { 463 rl.setLocalMovesAllowed( 464 ((String) ((JComboBox<?>) value).getSelectedItem()).equals(Bundle.getMessage("yes"))); 465 } 466 467 private int _maxTrainLength = Setup.getMaxTrainLength(); 468 469 public int getLastMaxTrainLength() { 470 return _maxTrainLength; 471 } 472 473 private void setTravel(Object value, RouteLocation rl) { 474 int wait = (int) value; 475 rl.setWait(wait - Setup.getTravelTime()); 476 } 477 478 private void setDepartureTime(Object value, RouteLocation rl) { 479 rl.setDepartureTime(((String) ((JComboBox<?>) value).getSelectedItem())); 480 } 481 482 private void setMaxTrainLength(Object value, RouteLocation rl) { 483 int length = (int) value; 484 if (length < 0) { 485 log.error("Maximum departure length must be a postive number"); 486 return; 487 } 488 if (length > Setup.getMaxTrainLength()) { 489 log.error("Maximum departure length can not exceed maximum train length"); 490 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("DepartureLengthNotExceed", 491 length, Setup.getMaxTrainLength()), Bundle.getMessage("CanNotChangeMaxLength"), 492 JmriJOptionPane.ERROR_MESSAGE); 493 return; 494 } 495 if (rl != _route.getTerminatesRouteLocation() && 496 (length < 500 && Setup.getLengthUnit().equals(Setup.FEET) || 497 length < 160 && Setup.getLengthUnit().equals(Setup.METER))) { 498 // warn that train length might be too short 499 if (JmriJOptionPane.showConfirmDialog(null, Bundle.getMessage("LimitTrainLength", 500 length, Setup.getLengthUnit().toLowerCase(), rl.getName()), 501 Bundle.getMessage("WarningTooShort"), 502 JmriJOptionPane.OK_CANCEL_OPTION) != JmriJOptionPane.OK_OPTION) { 503 return; 504 } 505 } 506 rl.setMaxTrainLength(length); 507 _maxTrainLength = length; 508 } 509 510 private void setGrade(Object value, RouteLocation rl) { 511 double grade = (Double) value; 512 if (grade <= 6 && grade >= -6) { 513 rl.setGrade(grade); 514 } else { 515 log.error("Maximum grade is 6 percent"); 516 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("MaxGrade"), 517 Bundle.getMessage("CanNotChangeGrade"), 518 JmriJOptionPane.ERROR_MESSAGE); 519 } 520 } 521 522 private void setTrainIconX(Object value, RouteLocation rl) { 523 int x = (int) value; 524 rl.setTrainIconX(x); 525 } 526 527 private void setTrainIconY(Object value, RouteLocation rl) { 528 int y = (int) value; 529 rl.setTrainIconY(y); 530 } 531 532 private void setComment(RouteLocation rl) { 533 // Create comment panel 534 final JDialog dialog = new JDialog(); 535 dialog.setLayout(new BorderLayout()); 536 dialog.setTitle(Bundle.getMessage("Comment") + " " + rl.getName()); 537 final JTextArea commentTextArea = new JTextArea(5, 100); 538 JScrollPane commentScroller = new JScrollPane(commentTextArea); 539 dialog.add(commentScroller, BorderLayout.CENTER); 540 commentTextArea.setText(rl.getComment()); 541 542 JPanel buttonPane = new JPanel(); 543 buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER)); 544 dialog.add(buttonPane, BorderLayout.SOUTH); 545 546 // text color chooser 547 JPanel pTextColor = new JPanel(); 548 pTextColor.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TextColor"))); 549 JColorChooser commentColorChooser = new JColorChooser(rl.getCommentColor()); 550 AbstractColorChooserPanel commentColorPanels[] = {new SplitButtonColorChooserPanel()}; 551 commentColorChooser.setChooserPanels(commentColorPanels); 552 commentColorChooser.setPreviewPanel(new JPanel()); 553 pTextColor.add(commentColorChooser); 554 buttonPane.add(pTextColor); 555 556 JButton okayButton = new JButton(Bundle.getMessage("ButtonOK")); 557 okayButton.addActionListener(new ActionListener() { 558 @Override 559 public void actionPerformed(ActionEvent arg0) { 560 rl.setComment(commentTextArea.getText()); 561 rl.setCommentColor(commentColorChooser.getColor()); 562 dialog.dispose(); 563 return; 564 } 565 }); 566 buttonPane.add(okayButton); 567 568 JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel")); 569 cancelButton.addActionListener(new ActionListener() { 570 @Override 571 public void actionPerformed(ActionEvent arg0) { 572 dialog.dispose(); 573 return; 574 } 575 }); 576 buttonPane.add(cancelButton); 577 578 dialog.setModal(true); 579 dialog.pack(); 580 dialog.setVisible(true); 581 } 582 583 private JComboBox<String> getYesNoComboBox() { 584 JComboBox<String> cb = new JComboBox<>(); 585 cb.addItem(Bundle.getMessage("yes")); 586 cb.addItem(Bundle.getMessage("no")); 587 return cb; 588 } 589 590 private JComboBox<String> getRandomControlComboBox() { 591 JComboBox<String> cb = new JComboBox<>(); 592 cb.addItem(RouteLocation.DISABLED); 593 // 10 to 100 by 10 594 for (int i = 10; i < 101; i = i + 10) { 595 cb.addItem(Integer.toString(i)); 596 } 597 return cb; 598 } 599 600 protected JComboBox<String> getTimeComboBox() { 601 JComboBox<String> timeBox = new JComboBox<>(); 602 String hour; 603 String minute; 604 timeBox.addItem(""); 605 for (int i = 0; i < 24; i++) { 606 if (i < 10) { 607 hour = "0" + Integer.toString(i); 608 } else { 609 hour = Integer.toString(i); 610 } 611 for (int j = 0; j < 60; j += 1) { 612 if (j < 10) { 613 minute = "0" + Integer.toString(j); 614 } else { 615 minute = Integer.toString(j); 616 } 617 618 timeBox.addItem(hour + ":" + minute); 619 } 620 } 621 return timeBox; 622 } 623 624 private void setLocationToolTip(RouteLocation rl) { 625 String text = Bundle.getMessage("TipTrainDirection", rl.getName(), rl.getTrainDirectionString()); 626 if (rl == _route.getTerminatesRouteLocation()) { 627 text = Bundle.getMessage("TipTrainTerminates", rl.getName()); 628 } 629 setToolTip(text, NAME_COLUMN); 630 } 631 632 private void setToolTip(String text, int col) { 633 XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel(); 634 JComponent jC = (JComponent) tcm.getColumnByModelIndex(col).getCellRenderer(); 635 if (jC != null) { 636 jC.setToolTipText(text); 637 } 638 } 639 640 // this table listens for changes to a route and it's locations 641 @Override 642 public void propertyChange(PropertyChangeEvent e) { 643 if (Control.SHOW_PROPERTY) { 644 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 645 .getNewValue()); 646 } 647 if (e.getPropertyName().equals(Route.LISTCHANGE_CHANGED_PROPERTY)) { 648 updateList(); 649 fireTableDataChanged(); 650 } 651 if (e.getPropertyName().equals(Setup.TRAIN_DIRECTION_PROPERTY_CHANGE) || 652 e.getPropertyName().equals(Setup.TRAVEL_TIME_PROPERTY_CHANGE)) { 653 fireTableDataChanged(); 654 } 655 if (e.getSource().getClass().equals(RouteLocation.class)) { 656 RouteLocation rl = (RouteLocation) e.getSource(); 657 int row = _routeList.indexOf(rl); 658 if (Control.SHOW_PROPERTY) { 659 log.debug("Update route table row: {} id: {}", row, rl.getId()); 660 } 661 if (row >= 0) { 662 fireTableRowsUpdated(row, row); 663 } 664 } 665 } 666 667 private void removePropertyChangeRouteLocations() { 668 for (RouteLocation rl : _routeList) { 669 rl.removePropertyChangeListener(this); 670 } 671 } 672 673 public void dispose() { 674 removePropertyChangeRouteLocations(); 675 if (_route != null) { 676 _route.removePropertyChangeListener(this); 677 } 678 Setup.getDefault().removePropertyChangeListener(this); 679 _routeList.clear(); 680 fireTableDataChanged(); 681 } 682 683 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteEditTableModel.class); 684}