001package jmri.jmrit.display.layoutEditor.configurexml; 002 003import java.awt.geom.Point2D; 004 005import jmri.Turnout; 006import jmri.jmrit.display.layoutEditor.*; 007import org.jdom2.Attribute; 008import org.jdom2.DataConversionException; 009import org.jdom2.Element; 010 011/** 012 * This module handles configuration for display.LayoutTurnout objects for a 013 * LayoutEditor. 014 * 015 * @author David Duchamp Copyright (c) 2007 016 * @author George Warner Copyright (c) 2017-2019 017 * @author Bob Jacobsen Copyright (c) 2020 018 */ 019public class LayoutTurnoutViewXml extends LayoutTrackViewXml { 020 021 static final EnumIO<LayoutTurnout.LinkType> linkEnumMap = new EnumIoNamesNumbers<>(LayoutTurnout.LinkType.class); 022 static final EnumIO<LayoutTurnout.TurnoutType> tTypeEnumMap = new EnumIoNamesNumbers<>(LayoutTurnout.TurnoutType.class); 023 024 public LayoutTurnoutViewXml() { 025 } 026 027 protected void addClass(Element element) { 028 element.setAttribute("class", "jmri.jmrit.display.layoutEditor.configurexml.LayoutTurnoutXml"); 029 } 030 031 /** 032 * Default implementation for storing the contents of a LayoutTurnout 033 * 034 * @param o Object to store, of type LayoutTurnout 035 * @return Element containing the complete info 036 */ 037 @Override 038 public Element store(Object o) { 039 040 LayoutTurnoutView pv = (LayoutTurnoutView) o; 041 LayoutTurnout p = pv.getLayoutTurnout(); 042 043 Element element = new Element("layoutturnout"); 044 045 // include attributes 046 element.setAttribute("ident", p.getName()); 047 element.setAttribute("type", tTypeEnumMap.outputFromEnum(p.getTurnoutType())); 048 049 element.setAttribute("hidden", "" + (pv.isHidden() ? "yes" : "no")); 050 element.setAttribute("disabled", "" + (p.isDisabled() ? "yes" : "no")); 051 element.setAttribute("disableWhenOccupied", "" + (p.isDisabledWhenOccupied() ? "yes" : "no")); 052 053 if (p.showToolTip()) { 054 element.setAttribute("showtooltip", "yes"); 055 } 056 057 element.setAttribute("continuing", "" + p.getContinuingSense()); 058 059 Point2D coords = pv.getCoordsCenter(); 060 element.setAttribute("xcen", "" + coords.getX()); 061 element.setAttribute("ycen", "" + coords.getY()); 062 063 coords = pv.getCoordsA(); 064 element.setAttribute("xa", "" + coords.getX()); 065 element.setAttribute("ya", "" + coords.getY()); 066 067 coords = pv.getCoordsB(); 068 element.setAttribute("xb", "" + coords.getX()); 069 element.setAttribute("yb", "" + coords.getY()); 070 071 coords = pv.getCoordsC(); 072 element.setAttribute("xc", "" + coords.getX()); 073 element.setAttribute("yc", "" + coords.getY()); 074 075 coords = pv.getCoordsD(); 076 element.setAttribute("xd", "" + coords.getX()); 077 element.setAttribute("yd", "" + coords.getY()); 078 079 element.setAttribute("ver", "" + p.getVersion()); 080 081 addClass(element); 082 083 if (!p.getTurnoutName().isEmpty()) { 084 element.setAttribute("turnoutname", p.getTurnoutName()); 085 } 086 if (!p.getSecondTurnoutName().isEmpty()) { 087 element.setAttribute("secondturnoutname", p.getSecondTurnoutName()); 088 if (p.isSecondTurnoutInverted()) { 089 element.setAttribute("secondturnoutinverted", "true"); 090 } 091 } 092 093 if (!p.getLinkedTurnoutName().isEmpty()) { 094 element.setAttribute("linkedturnoutname", p.getLinkedTurnoutName()); 095 element.setAttribute("linktype", "" + linkEnumMap.outputFromEnum(p.getLinkType())); 096 } 097 098 if (!p.getBlockName().isEmpty()) { 099 element.setAttribute("blockname", p.getBlockName()); 100 } 101 // Only save these if they're different from block A 102 if (!p.getBlockBName().isEmpty() && (!p.getBlockBName().equals(p.getBlockName()))) { 103 element.setAttribute("blockbname", p.getBlockBName()); 104 } 105 if (!p.getBlockCName().isEmpty() && (!p.getBlockCName().equals(p.getBlockName()))) { 106 element.setAttribute("blockcname", p.getBlockCName()); 107 } 108 if (!p.getBlockDName().isEmpty() && (!p.getBlockDName().equals(p.getBlockName()))) { 109 element.setAttribute("blockdname", p.getBlockDName()); 110 } 111 112 if (p.getConnectA() != null) { 113 element.setAttribute("connectaname", ((TrackSegment) p.getConnectA()).getId()); 114 } 115 if (p.getConnectB() != null) { 116 element.setAttribute("connectbname", ((TrackSegment) p.getConnectB()).getId()); 117 } 118 if (p.getConnectC() != null) { 119 element.setAttribute("connectcname", ((TrackSegment) p.getConnectC()).getId()); 120 } 121 if (p.getConnectD() != null) { 122 element.setAttribute("connectdname", ((TrackSegment) p.getConnectD()).getId()); 123 } 124 125 if (!p.getSignalA1Name().isEmpty()) { 126 element.setAttribute("signala1name", p.getSignalA1Name()); 127 } 128 if (!p.getSignalA2Name().isEmpty()) { 129 element.setAttribute("signala2name", p.getSignalA2Name()); 130 } 131 if (!p.getSignalA3Name().isEmpty()) { 132 element.setAttribute("signala3name", p.getSignalA3Name()); 133 } 134 if (!p.getSignalB1Name().isEmpty()) { 135 element.setAttribute("signalb1name", p.getSignalB1Name()); 136 } 137 if (!p.getSignalB2Name().isEmpty()) { 138 element.setAttribute("signalb2name", p.getSignalB2Name()); 139 } 140 if (!p.getSignalC1Name().isEmpty()) { 141 element.setAttribute("signalc1name", p.getSignalC1Name()); 142 } 143 if (!p.getSignalC2Name().isEmpty()) { 144 element.setAttribute("signalc2name", p.getSignalC2Name()); 145 } 146 if (!p.getSignalD1Name().isEmpty()) { 147 element.setAttribute("signald1name", p.getSignalD1Name()); 148 } 149 if (!p.getSignalD2Name().isEmpty()) { 150 element.setAttribute("signald2name", p.getSignalD2Name()); 151 } 152 153 if (!p.getSignalAMastName().isEmpty()) { 154 element.addContent(new Element("signalAMast").addContent(p.getSignalAMastName())); 155 } 156 157 if (!p.getSignalBMastName().isEmpty()) { 158 element.addContent(new Element("signalBMast").addContent(p.getSignalBMastName())); 159 } 160 if (!p.getSignalCMastName().isEmpty()) { 161 element.addContent(new Element("signalCMast").addContent(p.getSignalCMastName())); 162 } 163 if (!p.getSignalDMastName().isEmpty()) { 164 element.addContent(new Element("signalDMast").addContent(p.getSignalDMastName())); 165 } 166 167 if (!p.getSensorAName().isEmpty()) { 168 element.addContent(new Element("sensorA").addContent(p.getSensorAName())); 169 } 170 171 if (!p.getSensorBName().isEmpty()) { 172 element.addContent(new Element("sensorB").addContent(p.getSensorBName())); 173 } 174 if (!p.getSensorCName().isEmpty()) { 175 element.addContent(new Element("sensorC").addContent(p.getSensorCName())); 176 } 177 if (!p.getSensorDName().isEmpty()) { 178 element.addContent(new Element("sensorD").addContent(p.getSensorDName())); 179 } 180 storeLogixNG_Data(pv, element); 181 return element; 182 } 183 184 @Override 185 public boolean load(Element shared, Element perNode) { 186 log.error("Invalid method called"); 187 return false; 188 } 189 190 /** 191 * Load, starting with the levelxing element, then all the other data 192 * 193 * @param element Top level Element to unpack. 194 * @param o LayoutEditor as an Object 195 */ 196 @Override 197 public void load(Element element, Object o) { 198 // create the objects 199 LayoutEditor p = (LayoutEditor) o; 200 201 // get center point 202 String name = element.getAttribute("ident").getValue(); 203 double x = 0.0; 204 double y = 0.0; 205 LayoutTurnout.TurnoutType type = LayoutTurnout.TurnoutType.NONE; 206 try { 207 x = element.getAttribute("xcen").getFloatValue(); 208 y = element.getAttribute("ycen").getFloatValue(); 209 type = tTypeEnumMap.inputFromAttribute(element.getAttribute("type")); 210 } catch (org.jdom2.DataConversionException e) { 211 log.error("failed to convert layoutturnout attribute"); 212 } 213 214 int version = 1; 215 try { 216 if (element.getAttribute("ver") != null) { 217 version = element.getAttribute("ver").getIntValue(); 218 } 219 } catch (org.jdom2.DataConversionException e) { 220 log.error("failed to convert layoutturnout version attribute"); 221 } 222 223 // create the new LayoutTurnout of the correct type 224 LayoutTurnoutView lv; 225 LayoutTurnout l; 226 227 switch(type) { 228 229 case RH_TURNOUT : 230 LayoutRHTurnout lrht = new LayoutRHTurnout(name, p, version); 231 l = lrht; 232 lv = new LayoutRHTurnoutView(lrht, new Point2D.Double(x, y), 0.0, 1.0, 1.0, p); 233 break; 234 case LH_TURNOUT : 235 LayoutLHTurnout llht = new LayoutLHTurnout(name, p, version); 236 l = llht; 237 lv = new LayoutLHTurnoutView(llht, new Point2D.Double(x, y), 0.0, 1.0, 1.0, p); 238 break; 239 case WYE_TURNOUT : 240 LayoutWye lwt = new LayoutWye(name, p, version); 241 l = lwt; 242 lv = new LayoutWyeView(lwt, new Point2D.Double(x, y), 0.0, 1.0, 1.0, p); 243 break; 244 case DOUBLE_XOVER : 245 LayoutDoubleXOver ldx = new LayoutDoubleXOver(name, p, version); 246 l = ldx; 247 lv = new LayoutDoubleXOverView(ldx, new Point2D.Double(x, y), 0.0, 1.0, 1.0, p); 248 break; 249 case RH_XOVER : 250 LayoutRHXOver lrx = new LayoutRHXOver(name, p, version); 251 l = lrx; 252 lv = new LayoutRHXOverView(lrx, new Point2D.Double(x, y), 0.0, 1.0, 1.0, p); 253 break; 254 case LH_XOVER : 255 LayoutLHXOver llx = new LayoutLHXOver(name, p, version); 256 l = llx; 257 lv = new LayoutLHXOverView(llx, new Point2D.Double(x, y), 0.0, 1.0, 1.0, p); 258 break; 259 260 case DOUBLE_SLIP : 261 LayoutDoubleSlip lds = new LayoutDoubleSlip(name, p); 262 l = lds; 263 lv = new LayoutDoubleSlipView(lds, new Point2D.Double(x, y), 0.0, p); 264 log.error("Found DOUBLE_SLIP in LayoutTrack ctor for element {}", name); 265 break; 266 case SINGLE_SLIP : 267 LayoutSingleSlip lss = new LayoutSingleSlip(name, p); 268 l = lss; 269 lv = new LayoutSingleSlipView(lss, new Point2D.Double(x, y), 0.0, p); 270 log.error("Found SINGLE_SLIP in LayoutTrack ctor for element {}", name); 271 break; 272 273 default: 274 log.error("can't create LayoutTrack {} with type {}", name, type); 275 return; // without creating 276 } 277 278 p.addLayoutTrack(l, lv); 279 280 // get remaining attributes 281 Attribute a = element.getAttribute("turnoutname"); 282 if (a != null) { 283 l.setTurnout(a.getValue()); 284 } 285 a = element.getAttribute("secondturnoutname"); 286 if (a != null) { 287 l.setSecondTurnout(a.getValue()); 288 try { 289 l.setSecondTurnoutInverted(element.getAttribute("secondturnoutinverted").getBooleanValue()); 290 } catch (DataConversionException e1) { 291 log.warn("unable to convert layout turnout secondturnoutinverted attribute"); 292 } catch (NullPointerException e) { // considered normal if the attribute is not present 293 } 294 } 295 296 a = element.getAttribute("blockname"); 297 if (a != null) { 298 l.tBlockAName = a.getValue(); 299 } 300 a = element.getAttribute("blockbname"); 301 if (a != null) { 302 l.tBlockBName = a.getValue(); 303 } 304 a = element.getAttribute("blockcname"); 305 if (a != null) { 306 l.tBlockCName = a.getValue(); 307 } 308 a = element.getAttribute("blockdname"); 309 if (a != null) { 310 l.tBlockDName = a.getValue(); 311 } 312 313 a = element.getAttribute("connectaname"); 314 if (a != null) { 315 l.connectAName = a.getValue(); 316 } 317 a = element.getAttribute("connectbname"); 318 if (a != null) { 319 l.connectBName = a.getValue(); 320 } 321 a = element.getAttribute("connectcname"); 322 if (a != null) { 323 l.connectCName = a.getValue(); 324 } 325 a = element.getAttribute("connectdname"); 326 if (a != null) { 327 l.connectDName = a.getValue(); 328 } 329 330 a = element.getAttribute("signala1name"); 331 if (a != null) { 332 l.setSignalA1Name(a.getValue()); 333 } 334 a = element.getAttribute("signala2name"); 335 if (a != null) { 336 l.setSignalA2Name(a.getValue()); 337 } 338 a = element.getAttribute("signala3name"); 339 if (a != null) { 340 l.setSignalA3Name(a.getValue()); 341 } 342 a = element.getAttribute("signalb1name"); 343 if (a != null) { 344 l.setSignalB1Name(a.getValue()); 345 } 346 a = element.getAttribute("signalb2name"); 347 if (a != null) { 348 l.setSignalB2Name(a.getValue()); 349 } 350 a = element.getAttribute("signalc1name"); 351 if (a != null) { 352 l.setSignalC1Name(a.getValue()); 353 } 354 a = element.getAttribute("signalc2name"); 355 if (a != null) { 356 l.setSignalC2Name(a.getValue()); 357 } 358 a = element.getAttribute("signald1name"); 359 if (a != null) { 360 l.setSignalD1Name(a.getValue()); 361 } 362 a = element.getAttribute("signald2name"); 363 if (a != null) { 364 l.setSignalD2Name(a.getValue()); 365 } 366 a = element.getAttribute("linkedturnoutname"); 367 if (a != null) { 368 l.linkedTurnoutName = a.getValue(); 369 l.linkType = linkEnumMap.inputFromAttribute(element.getAttribute("linktype")); 370 } 371 a = element.getAttribute("continuing"); 372 if (a != null) { 373 int continuing = Turnout.CLOSED; 374 try { 375 continuing = element.getAttribute("continuing").getIntValue(); 376 } catch (org.jdom2.DataConversionException e) { 377 log.error("failed to convert continuingsense attribute"); 378 } 379 l.setContinuingSense(continuing); 380 } 381 try { 382 l.setDisabled(element.getAttribute("disabled").getBooleanValue()); 383 } catch (DataConversionException e1) { 384 log.warn("unable to convert layout turnout disabled attribute"); 385 } catch (NullPointerException e) { // considered normal if the attribute is not present 386 } 387 try { 388 l.setDisableWhenOccupied(element.getAttribute("disableWhenOccupied").getBooleanValue()); 389 } catch (DataConversionException e1) { 390 log.warn("unable to convert layout turnout disableWhenOccupied attribute"); 391 } catch (NullPointerException e) { // considered normal if the attribute is not present 392 } 393 try { 394 lv.setHidden(element.getAttribute("hidden").getBooleanValue()); 395 } catch (DataConversionException e1) { 396 log.warn("unable to convert layout turnout hidden attribute"); 397 } catch (NullPointerException e) { // considered normal if the attribute is not present 398 } 399 400 l.setShowToolTip(false); 401 a = element.getAttribute("showtooltip"); 402 if (a != null) { 403 if ("yes".equals(a.getValue())) { 404 l.setShowToolTip(true); 405 } 406 } 407 408 if (version == 2) { 409 try { 410 x = element.getAttribute("xa").getFloatValue(); 411 y = element.getAttribute("ya").getFloatValue(); 412 lv.setCoordsA(new Point2D.Double(x, y)); 413 } catch (org.jdom2.DataConversionException e) { 414 log.error("failed to convert layoutturnout b coords attribute"); 415 } catch (java.lang.NullPointerException e) { 416 //can be ignored as panel file may not support method 417 } 418 } 419 try { 420 x = element.getAttribute("xb").getFloatValue(); 421 y = element.getAttribute("yb").getFloatValue(); 422 lv.setCoordsB(new Point2D.Double(x, y)); 423 } catch (org.jdom2.DataConversionException e) { 424 log.error("failed to convert layoutturnout b coords attribute"); 425 } 426 try { 427 x = element.getAttribute("xc").getFloatValue(); 428 y = element.getAttribute("yc").getFloatValue(); 429 lv.setCoordsC(new Point2D.Double(x, y)); 430 } catch (org.jdom2.DataConversionException e) { 431 log.error("failed to convert layoutturnout c coords attribute"); 432 } 433 if (version == 2) { 434 try { 435 x = element.getAttribute("xd").getFloatValue(); 436 y = element.getAttribute("yd").getFloatValue(); 437 lv.setCoordsD(new Point2D.Double(x, y)); 438 } catch (org.jdom2.DataConversionException e) { 439 log.error("failed to convert layoutturnout c coords attribute"); 440 } catch (java.lang.NullPointerException e) { 441 //can be ignored as panel file may not support method 442 } 443 } 444 445 l.setSignalAMast(getElement(element, "signalAMast")); 446 l.setSignalBMast(getElement(element, "signalBMast")); 447 l.setSignalCMast(getElement(element, "signalCMast")); 448 l.setSignalDMast(getElement(element, "signalDMast")); 449 450 l.setSensorA(getElement(element, "sensorA")); 451 l.setSensorB(getElement(element, "sensorB")); 452 l.setSensorC(getElement(element, "sensorC")); 453 l.setSensorD(getElement(element, "sensorD")); 454 455 loadLogixNG_Data(lv, element); 456 } 457 458 String getElement(Element el, String child) { 459 if (el.getChild(child) != null) { 460 return el.getChild(child).getText(); 461 } 462 return ""; 463 } 464 465 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LayoutTurnoutViewXml.class); 466}