001package jmri.jmrit.operations.routes; 002 003import java.awt.Color; 004import java.awt.Point; 005 006import org.jdom2.Attribute; 007import org.jdom2.Element; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 012import jmri.InstanceManager; 013import jmri.beans.PropertyChangeSupport; 014import jmri.jmrit.operations.locations.Location; 015import jmri.jmrit.operations.locations.LocationManager; 016import jmri.jmrit.operations.setup.Control; 017import jmri.jmrit.operations.setup.Setup; 018import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 019import jmri.util.ColorUtil; 020 021/** 022 * Represents a location in a route, a location can appear more than once in a 023 * route. 024 * 025 * @author Daniel Boudreau Copyright (C) 2008, 2013, 2026 026 */ 027public class RouteLocation extends PropertyChangeSupport implements java.beans.PropertyChangeListener { 028 029 public static final String NONE = ""; 030 031 protected String _id = NONE; 032 protected Location _location = null; // the location in the route 033 protected String _locationId = NONE; // the location's id 034 protected int _trainDir = (Setup.getTrainDirection() == Setup.EAST + Setup.WEST) ? EAST : NORTH; // train direction 035 protected int _maxTrainLength = Setup.getMaxTrainLength(); 036 protected int _maxCarMoves = Setup.getCarMoves(); 037 protected String _randomControl = DISABLED; 038 protected boolean _drops = true; // when true set outs allowed at this location 039 protected boolean _pickups = true; // when true pick ups allowed at this location 040 protected boolean _localMoves = true; // when true local moves allowed at this location 041 protected int _sequenceNum = 0; // used to determine location order in a route 042 protected double _grade = 0; // maximum grade between locations 043 protected int _wait = 0; // wait time at this location 044 protected String _departureTime = NONE; // hh:mm departure time from this location 045 protected String _departureDay = "0"; // departure day from this location 046 protected int _trainIconX = 0; // the x & y coordinates for the train icon 047 protected int _trainIconY = 0; 048 protected int _blockingOrder = 0; 049 protected String _comment = NONE; 050 protected Color _commentColor = Color.black; 051 protected boolean _bold = false; // when true bold text 052 053 protected int _carMoves = 0; // number of moves at this location 054 protected int _trainWeight = 0; // total car weight departing this location 055 protected int _trainLength = 0; // train length departing this location 056 057 public static final int EAST = 1; // train direction 058 public static final int WEST = 2; 059 public static final int NORTH = 4; 060 public static final int SOUTH = 8; 061 062 public static final String EAST_DIR = Setup.EAST_DIR; // train directions text 063 public static final String WEST_DIR = Setup.WEST_DIR; 064 public static final String NORTH_DIR = Setup.NORTH_DIR; 065 public static final String SOUTH_DIR = Setup.SOUTH_DIR; 066 067 public static final String DISPOSE = "routeLocationDispose"; // NOI18N 068 public static final String DELETED = Bundle.getMessage("locationDeleted"); 069 070 public static final String DROP_CHANGED_PROPERTY = "dropChange"; // NOI18N 071 public static final String PICKUP_CHANGED_PROPERTY = "pickupChange"; // NOI18N 072 public static final String LOCAL_MOVES_CHANGED_PROPERTY = "localMovesChange"; // NOI18N 073 public static final String MAX_MOVES_CHANGED_PROPERTY = "maxMovesChange"; // NOI18N 074 public static final String TRAIN_DIRECTION_CHANGED_PROPERTY = "trainDirectionChange"; // NOI18N 075 public static final String DEPARTURE_TIME_CHANGED_PROPERTY = "routeDepartureTimeChange"; // NOI18N 076 public static final String MAX_LENGTH_CHANGED_PROPERTY = "maxLengthChange"; // NOI18N 077 078 public static final String DISABLED = "Off"; 079 080 public RouteLocation(String id, Location location) { 081 log.debug("New route location ({}) id: {}", location.getName(), id); 082 _location = location; 083 _id = id; 084 // listen for name change or delete 085 location.addPropertyChangeListener(this); 086 } 087 088 // for combo boxes 089 @Override 090 public String toString() { 091 return getName(); 092 } 093 094 public String getId() { 095 return _id; 096 } 097 098 public String getName() { 099 if (getLocation() != null) { 100 return getLocation().getName(); 101 } 102 return DELETED; 103 } 104 105 public String getSplitName() { 106 if (getLocation() != null) { 107 return getLocation().getSplitName(); 108 } 109 return DELETED; 110 } 111 112 private String getNameId() { 113 if (_location != null) { 114 return _location.getId(); 115 } 116 return _locationId; 117 } 118 119 public Location getLocation() { 120 return _location; 121 } 122 123 public int getSequenceNumber() { 124 return _sequenceNum; 125 } 126 127 public void setSequenceNumber(int sequence) { 128 // property change not needed 129 _sequenceNum = sequence; 130 } 131 132 public int getBlockingOrder() { 133 return _blockingOrder; 134 } 135 136 public void setBlockingOrder(int order) { 137 _blockingOrder = order; 138 } 139 140 public void setComment(String comment) { 141 String old = _comment; 142 _comment = comment; 143 if (!old.equals(_comment)) { 144 setDirtyAndFirePropertyChange("RouteLocationComment", old, comment); // NOI18N 145 } 146 } 147 148 public String getComment() { 149 return _comment; 150 } 151 152 /** 153 * Sets the text color for the route comment 154 * 155 * @param color The color of the text 156 */ 157 public void setCommentColor(Color color) { 158 Color old = _commentColor; 159 _commentColor = color; 160 if (!old.equals(_commentColor)) { 161 setDirtyAndFirePropertyChange("RouteLocationCommentColor", old, color); // NOI18N 162 } 163 } 164 165 public Color getCommentColor() { 166 return _commentColor; 167 } 168 169 public boolean isCommentBoldEnabled() { 170 return _bold; 171 } 172 173 public void setCommentBoldEnabled(boolean enabled) { 174 boolean old = _bold; 175 _bold = enabled; 176 if (old != _bold) { 177 setDirtyAndFirePropertyChange("RouteLocationBoldText", old, enabled); // NOI18N 178 } 179 } 180 181 public String getCommentWithColor() { 182 return TrainCommon.formatColorString(getComment(), getCommentColor(), isCommentBoldEnabled()); 183 } 184 185 public void setCommentTextColor(String color) { 186 setCommentColor(ColorUtil.stringToColor(color)); 187 } 188 189 public String getCommentTextColor() { 190 return ColorUtil.colorToColorName(getCommentColor()); 191 } 192 193 public void setTrainDirection(int direction) { 194 int old = _trainDir; 195 _trainDir = direction; 196 if (old != direction) { 197 setDirtyAndFirePropertyChange(TRAIN_DIRECTION_CHANGED_PROPERTY, old, direction); 198 } 199 } 200 201 /** 202 * Gets the binary representation of the train's direction at this location 203 * 204 * @return int representing train direction EAST WEST NORTH SOUTH 205 */ 206 public int getTrainDirection() { 207 return _trainDir; 208 } 209 210 /** 211 * Gets the String representation of the train's direction at this location 212 * 213 * @return String representing train direction at this location 214 */ 215 public String getTrainDirectionString() { 216 return Setup.getDirectionString(getTrainDirection()); 217 } 218 219 public void setMaxTrainLength(int length) { 220 int old = _maxTrainLength; 221 _maxTrainLength = length; 222 if (old != length) { 223 setDirtyAndFirePropertyChange(MAX_LENGTH_CHANGED_PROPERTY, old, length); 224 } 225 } 226 227 public int getMaxTrainLength() { 228 return _maxTrainLength; 229 } 230 231 /** 232 * Set the train length departing this location when building a train 233 * 234 * @param length The train's current length. 235 */ 236 public void setTrainLength(int length) { 237 int old = _trainLength; 238 _trainLength = length; 239 if (old != length) { 240 firePropertyChange("trainLength", old, length); // NOI18N 241 } 242 } 243 244 public int getTrainLength() { 245 return _trainLength; 246 } 247 248 /** 249 * Set the train weight departing this location when building a train 250 * 251 * @param weight The train's current weight. 252 */ 253 public void setTrainWeight(int weight) { 254 int old = _trainWeight; 255 _trainWeight = weight; 256 if (old != weight) { 257 firePropertyChange("trainWeight", old, weight); // NOI18N 258 } 259 } 260 261 public int getTrainWeight() { 262 return _trainWeight; 263 } 264 265 public void setMaxCarMoves(int moves) { 266 int old = _maxCarMoves; 267 _maxCarMoves = moves; 268 if (old != moves) { 269 setDirtyAndFirePropertyChange(MAX_MOVES_CHANGED_PROPERTY, old, moves); 270 } 271 } 272 273 /** 274 * Get the maximum number of moves for this location 275 * 276 * @return maximum number of moves 277 */ 278 public int getMaxCarMoves() { 279 return _maxCarMoves; 280 } 281 282 public void setRandomControl(String value) { 283 String old = _randomControl; 284 _randomControl = value; 285 if (!old.equals(value)) { 286 setDirtyAndFirePropertyChange("randomControl", old, value); // NOI18N 287 } 288 } 289 290 public String getRandomControl() { 291 return _randomControl; 292 } 293 294 /** 295 * When true allow car drops at this location 296 * 297 * @param drops when true drops allowed at this location 298 */ 299 public void setDropAllowed(boolean drops) { 300 boolean old = _drops; 301 _drops = drops; 302 if (old != drops) { 303 setDirtyAndFirePropertyChange(DROP_CHANGED_PROPERTY, old, drops); 304 } 305 } 306 307 public boolean isDropAllowed() { 308 return _drops; 309 } 310 311 /** 312 * When true allow car pick ups at this location 313 * 314 * @param pickups when true pick ups allowed at this location 315 */ 316 public void setPickUpAllowed(boolean pickups) { 317 boolean old = _pickups; 318 _pickups = pickups; 319 if (old != pickups) { 320 setDirtyAndFirePropertyChange(PICKUP_CHANGED_PROPERTY, old, pickups); 321 } 322 } 323 324 public boolean isPickUpAllowed() { 325 return _pickups; 326 } 327 328 /** 329 * When true allow local car moves at this location 330 * 331 * @param local when true local moves allowed at this location 332 */ 333 public void setLocalMovesAllowed(boolean local) { 334 boolean old = _localMoves; 335 _localMoves = local; 336 if (old != local) { 337 setDirtyAndFirePropertyChange(LOCAL_MOVES_CHANGED_PROPERTY, old, local); 338 } 339 } 340 341 public boolean isLocalMovesAllowed() { 342 return _localMoves; 343 } 344 345 /** 346 * Set the number of moves completed when building a train 347 * 348 * @param moves An integer representing the amount of moves completed. 349 */ 350 public void setCarMoves(int moves) { 351 int old = _carMoves; 352 _carMoves = moves; 353 if (old != moves) { 354 firePropertyChange("carMoves", old, moves); // NOI18N 355 } 356 } 357 358 public int getCarMoves() { 359 return _carMoves; 360 } 361 362 public void setWait(int time) { 363 int old = _wait; 364 _wait = time; 365 if (old != time) { 366 setDirtyAndFirePropertyChange("waitTime", old, time); // NOI18N 367 } 368 } 369 370 public int getWait() { 371 return _wait; 372 } 373 374 /** 375 * Sets the formated departure time from this location 376 * 377 * @param time format hours:minutes 378 */ 379 public void setDepartureTimeHourMinutes(String time) { 380 String old = _departureTime; 381 _departureTime = time; 382 if (!old.equals(time)) { 383 setDirtyAndFirePropertyChange(DEPARTURE_TIME_CHANGED_PROPERTY, old, time); 384 } 385 } 386 387 public String getDepartureTimeHourMinutes() { 388 return _departureTime; 389 } 390 391 /** 392 * Sets the departure time from this route location 393 * 394 * @param time days:hours:minutes or hours:minutes or NONE 395 */ 396 public void setDepartureTime(String time) { 397 String[] t = time.split(":"); 398 if (t.length > 2) { 399 setDepartureTime(t[0], t[1], t[2]); 400 } else if (t.length > 1) { 401 setDepartureTime("0", t[0], t[1]); 402 } else { 403 setDepartureTimeHourMinutes(NONE); 404 } 405 } 406 407 public void setDepartureTime(String day, String hour, String minute) { 408 setDepartureTimeDay(day); 409 hour = String.format("%02d", Integer.parseInt(hour)); 410 minute = String.format("%02d", Integer.parseInt(minute)); 411 String time = hour + ":" + minute; 412 setDepartureTimeHourMinutes(time); 413 } 414 415 /** 416 * @return departure time day:hour:minutes 417 */ 418 public String getDepartureTime() { 419 return getDepartureTimeDay() + ":" + getDepartureTimeHourMinutes(); 420 } 421 422 /** 423 * Sets the departure day from this route location 424 * 425 * @param day the day where "0" is today, and "1, 2 .." are the following 426 * days. 427 */ 428 public void setDepartureTimeDay(String day) { 429 String old = _departureDay; 430 if (!old.equals(day)) { 431 setDirtyAndFirePropertyChange(DEPARTURE_TIME_CHANGED_PROPERTY, old, day); 432 } 433 _departureDay = day; 434 } 435 436 public String getDepartureTimeDay() { 437 return _departureDay; 438 } 439 440 public String getDepartureTimeHour() { 441 String[] time = getDepartureTime().split(":"); 442 return time[1]; 443 } 444 445 public String getDepartureTimeMinute() { 446 String[] time = getDepartureTime().split(":"); 447 return time[2]; 448 } 449 450 /** 451 * Gets the formated departure time from this route location. Provides the 452 * day at the start if day is greater than zero. Format days:hours:minutes 453 * or hours:minutes if day = 0. Optional AM or PM 12 hour format. 454 * 455 * @return days:hours:minutes or hours:minutes. Optional AM/PM 456 */ 457 public String getFormatedDepartureTime() { 458 if (getDepartureTimeHourMinutes().equals(NONE)) { 459 return NONE; 460 } 461 String sDay = ""; 462 if (!getDepartureTimeDay().equals("0")) { 463 sDay = getDepartureTimeDay() + ":"; 464 } 465 if (!Setup.is12hrFormatEnabled()) { 466 return sDay + getDepartureTimeHourMinutes(); 467 } 468 String AM_PM = TrainCommon.SPACE + Bundle.getMessage("AM"); 469 int hour = Integer.parseInt(getDepartureTimeHour()); 470 if (hour >= 12) { 471 AM_PM = TrainCommon.SPACE + Bundle.getMessage("PM"); 472 hour = hour - 12; 473 } 474 if (hour == 0) { 475 hour = 12; 476 } 477 String shour = Integer.toString(hour); 478 return sDay + shour + ":" + getDepartureTimeMinute() + AM_PM; 479 } 480 481 @SuppressFBWarnings(value = "FE_FLOATING_POINT_EQUALITY", justification = "firing property change doesn't matter") 482 public void setGrade(double grade) { 483 double old = _grade; 484 _grade = grade; 485 if (old != grade) { 486 setDirtyAndFirePropertyChange("grade", old, grade); // NOI18N 487 } 488 } 489 490 public double getGrade() { 491 return _grade; 492 } 493 494 public void setTrainIconX(int x) { 495 int old = _trainIconX; 496 _trainIconX = x; 497 if (old != x) { 498 setDirtyAndFirePropertyChange("trainIconX", old, x); // NOI18N 499 } 500 } 501 502 public int getTrainIconX() { 503 return _trainIconX; 504 } 505 506 public void setTrainIconY(int y) { 507 int old = _trainIconY; 508 _trainIconY = y; 509 if (old != y) { 510 setDirtyAndFirePropertyChange("trainIconY", old, y); // NOI18N 511 } 512 } 513 514 public int getTrainIconY() { 515 return _trainIconY; 516 } 517 518 /** 519 * Gets the X range for detecting the manual movement of a train icon. 520 * 521 * @return the range for detection 522 */ 523 public int getTrainIconRangeX() { 524 return getLocation().getTrainIconRangeX(); 525 } 526 527 /** 528 * Gets the Y range for detecting the manual movement of a train icon. 529 * 530 * @return the range for detection 531 */ 532 public int getTrainIconRangeY() { 533 return getLocation().getTrainIconRangeY(); 534 } 535 536 /** 537 * Set the train icon panel coordinates to the location defaults. 538 * Coordinates are dependent on the train's departure direction. 539 */ 540 public void setTrainIconCoordinates() { 541 Location l = InstanceManager.getDefault(LocationManager.class).getLocationByName(getName()); 542 if ((getTrainDirection() & Location.EAST) == Location.EAST) { 543 setTrainIconX(l.getTrainIconEast().x); 544 setTrainIconY(l.getTrainIconEast().y); 545 } 546 if ((getTrainDirection() & Location.WEST) == Location.WEST) { 547 setTrainIconX(l.getTrainIconWest().x); 548 setTrainIconY(l.getTrainIconWest().y); 549 } 550 if ((getTrainDirection() & Location.NORTH) == Location.NORTH) { 551 setTrainIconX(l.getTrainIconNorth().x); 552 setTrainIconY(l.getTrainIconNorth().y); 553 } 554 if ((getTrainDirection() & Location.SOUTH) == Location.SOUTH) { 555 setTrainIconX(l.getTrainIconSouth().x); 556 setTrainIconY(l.getTrainIconSouth().y); 557 } 558 } 559 560 public Point getTrainIconCoordinates() { 561 return new Point(getTrainIconX(), getTrainIconY()); 562 } 563 564 public void dispose() { 565 if (_location != null) { 566 _location.removePropertyChangeListener(this); 567 } 568 firePropertyChange(DISPOSE, null, DISPOSE); 569 } 570 571 /** 572 * Construct this Entry from XML. This member has to remain synchronized 573 * with the detailed DTD in operations-config.xml 574 * 575 * @param e Consist XML element 576 */ 577 public RouteLocation(Element e) { 578 Attribute a; 579 if ((a = e.getAttribute(Xml.ID)) != null) { 580 _id = a.getValue(); 581 } else { 582 log.warn("no id attribute in route location element when reading operations"); 583 } 584 if ((a = e.getAttribute(Xml.LOCATION_ID)) != null) { 585 _locationId = a.getValue(); 586 _location = InstanceManager.getDefault(LocationManager.class).getLocationById(a.getValue()); 587 if (_location != null) { 588 _location.addPropertyChangeListener(this); 589 } 590 } // old way of storing a route location 591 else if ((a = e.getAttribute(Xml.NAME)) != null) { 592 _location = InstanceManager.getDefault(LocationManager.class).getLocationByName(a.getValue()); 593 if (_location != null) { 594 _location.addPropertyChangeListener(this); 595 } 596 // force rewrite of route file 597 InstanceManager.getDefault(RouteManagerXml.class).setDirty(true); 598 } 599 if ((a = e.getAttribute(Xml.TRAIN_DIRECTION)) != null) { 600 // early releases had text for train direction 601 if (Setup.getTrainDirectionList().contains(a.getValue())) { 602 _trainDir = Setup.getDirectionInt(a.getValue()); 603 log.debug("found old train direction {} new direction {}", a.getValue(), _trainDir); 604 } else { 605 try { 606 _trainDir = Integer.parseInt(a.getValue()); 607 } catch (NumberFormatException ee) { 608 log.error("Route location ({}) direction ({}) is unknown", getName(), a.getValue()); 609 } 610 } 611 } 612 if ((a = e.getAttribute(Xml.MAX_TRAIN_LENGTH)) != null) { 613 try { 614 _maxTrainLength = Integer.parseInt(a.getValue()); 615 } catch (NumberFormatException ee) { 616 log.error("Route location ({}) maximum train length ({}) isn't a valid number", getName(), 617 a.getValue()); 618 } 619 } 620 if ((a = e.getAttribute(Xml.GRADE)) != null) { 621 try { 622 _grade = Double.parseDouble(a.getValue()); 623 } catch (NumberFormatException ee) { 624 log.error("Route location ({}) grade ({}) isn't a valid number", getName(), a.getValue()); 625 } 626 } 627 if ((a = e.getAttribute(Xml.MAX_CAR_MOVES)) != null) { 628 try { 629 _maxCarMoves = Integer.parseInt(a.getValue()); 630 } catch (NumberFormatException ee) { 631 log.error("Route location ({}) maximum car moves ({}) isn't a valid number", getName(), a.getValue()); 632 } 633 } 634 if ((a = e.getAttribute(Xml.RANDOM_CONTROL)) != null) { 635 _randomControl = a.getValue(); 636 } 637 if ((a = e.getAttribute(Xml.PICKUPS)) != null) { 638 _pickups = a.getValue().equals(Xml.YES); 639 } 640 if ((a = e.getAttribute(Xml.DROPS)) != null) { 641 _drops = a.getValue().equals(Xml.YES); 642 } 643 if ((a = e.getAttribute(Xml.LOCAL_MOVES)) != null) { 644 _localMoves = a.getValue().equals(Xml.YES); 645 } else { 646 if (!isPickUpAllowed() || !isDropAllowed()) { 647 _localMoves = false; // disable local moves 648 } 649 } 650 if ((a = e.getAttribute(Xml.WAIT)) != null) { 651 try { 652 _wait = Integer.parseInt(a.getValue()); 653 } catch (NumberFormatException ee) { 654 log.error("Route location ({}) wait ({}) isn't a valid number", getName(), a.getValue()); 655 } 656 } 657 if ((a = e.getAttribute(Xml.DEPART_DAY)) != null) { 658 _departureDay = a.getValue(); 659 } 660 if ((a = e.getAttribute(Xml.DEPART_TIME)) != null) { 661 _departureTime = a.getValue(); 662 } 663 if ((a = e.getAttribute(Xml.BLOCKING_ORDER)) != null) { 664 try { 665 _blockingOrder = Integer.parseInt(a.getValue()); 666 } catch (NumberFormatException ee) { 667 log.error("Route location ({}) blocking order ({}) isn't a valid number", getName(), a.getValue()); 668 } 669 } 670 if ((a = e.getAttribute(Xml.TRAIN_ICON_X)) != null) { 671 try { 672 _trainIconX = Integer.parseInt(a.getValue()); 673 } catch (NumberFormatException ee) { 674 log.error("Route location ({}) icon x ({}) isn't a valid number", getName(), a.getValue()); 675 } 676 } 677 if ((a = e.getAttribute(Xml.TRAIN_ICON_Y)) != null) { 678 try { 679 _trainIconY = Integer.parseInt(a.getValue()); 680 } catch (NumberFormatException ee) { 681 log.error("Route location ({}) icon y ({}) isn't a valid number", getName(), a.getValue()); 682 } 683 } 684 if ((a = e.getAttribute(Xml.SEQUENCE_ID)) != null) { 685 try { 686 _sequenceNum = Integer.parseInt(a.getValue()); 687 } catch (NumberFormatException ee) { 688 log.error("Route location ({}) sequence id isn't a valid number {}", getName(), a.getValue()); 689 } 690 } 691 if ((a = e.getAttribute(Xml.COMMENT_COLOR)) != null) { 692 setCommentTextColor(a.getValue()); 693 } 694 if ((a = e.getAttribute(Xml.COMMENT_BOLD)) != null) { 695 _bold = a.getValue().equals(Xml.YES); 696 } 697 if ((a = e.getAttribute(Xml.COMMENT)) != null) { 698 _comment = a.getValue(); 699 } 700 } 701 702 /** 703 * Create an XML element to represent this Entry. This member has to remain 704 * synchronized with the detailed DTD in operations-config.xml. 705 * 706 * @return Contents in a JDOM Element 707 */ 708 public Element store() { 709 Element e = new Element(Xml.LOCATION); 710 e.setAttribute(Xml.ID, getId()); 711 e.setAttribute(Xml.NAME, getName()); 712 e.setAttribute(Xml.LOCATION_ID, getNameId()); 713 e.setAttribute(Xml.SEQUENCE_ID, Integer.toString(getSequenceNumber())); 714 e.setAttribute(Xml.TRAIN_DIRECTION, Integer.toString(getTrainDirection())); 715 e.setAttribute(Xml.MAX_TRAIN_LENGTH, Integer.toString(getMaxTrainLength())); 716 e.setAttribute(Xml.GRADE, Double.toString(getGrade())); 717 e.setAttribute(Xml.MAX_CAR_MOVES, Integer.toString(getMaxCarMoves())); 718 e.setAttribute(Xml.RANDOM_CONTROL, getRandomControl()); 719 e.setAttribute(Xml.PICKUPS, isPickUpAllowed() ? Xml.YES : Xml.NO); 720 e.setAttribute(Xml.DROPS, isDropAllowed() ? Xml.YES : Xml.NO); 721 e.setAttribute(Xml.LOCAL_MOVES, isLocalMovesAllowed() ? Xml.YES : Xml.NO); 722 e.setAttribute(Xml.WAIT, Integer.toString(getWait())); 723 e.setAttribute(Xml.DEPART_DAY, getDepartureTimeDay()); 724 e.setAttribute(Xml.DEPART_TIME, getDepartureTimeHourMinutes()); 725 e.setAttribute(Xml.BLOCKING_ORDER, Integer.toString(getBlockingOrder())); 726 e.setAttribute(Xml.TRAIN_ICON_X, Integer.toString(getTrainIconX())); 727 e.setAttribute(Xml.TRAIN_ICON_Y, Integer.toString(getTrainIconY())); 728 e.setAttribute(Xml.COMMENT_COLOR, getCommentTextColor()); 729 e.setAttribute(Xml.COMMENT, getComment()); 730 e.setAttribute(Xml.COMMENT_BOLD, isCommentBoldEnabled() ? Xml.YES : Xml.NO); 731 return e; 732 } 733 734 @Override 735 public void propertyChange(java.beans.PropertyChangeEvent e) { 736 if (Control.SHOW_PROPERTY) { 737 log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e 738 .getNewValue()); 739 } 740 if (e.getPropertyName().equals(Location.DISPOSE_CHANGED_PROPERTY)) { 741 if (_location != null) { 742 _location.removePropertyChangeListener(this); 743 } 744 _location = null; 745 } 746 // forward property name change 747 if (e.getPropertyName().equals(Location.NAME_CHANGED_PROPERTY)) { 748 firePropertyChange(e.getPropertyName(), e.getOldValue(), e.getNewValue()); 749 } 750 } 751 752 protected void setDirtyAndFirePropertyChange(String p, Object old, Object n) { 753 InstanceManager.getDefault(RouteManagerXml.class).setDirty(true); 754 firePropertyChange(p, old, n); 755 } 756 757 private static final Logger log = LoggerFactory.getLogger(RouteLocation.class); 758 759}