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