001package jmri.jmrit.display.layoutEditor.configurexml; 002 003import java.awt.geom.Point2D; 004import jmri.jmrit.display.layoutEditor.*; 005import org.jdom2.Attribute; 006import org.jdom2.DataConversionException; 007import org.jdom2.Element; 008 009/** 010 * This module handles configuration for display.LayoutSlipView objects for a 011 * LayoutEditor. 012 * 013 * @author David Duchamp Copyright (c) 2007 014 * @author George Warner Copyright (c) 2017-2018 015 * @author Bob Jacobsen Copyright (c) 2020 016 */ 017public class LayoutSlipViewXml extends LayoutTrackViewXml { 018 019 public LayoutSlipViewXml() { 020 } 021 022 final static EnumIO<LayoutSlip.TurnoutType> tTypeEnumMap = new EnumIoNamesNumbers<>(LayoutSlip.TurnoutType.class); 023 024 protected void addClass(Element element) { 025 element.setAttribute("class", "jmri.jmrit.display.layoutEditor.configurexml.LayoutSlipXml"); 026 } 027 028 /** 029 * Default implementation for storing the contents of a LayoutSlip 030 * 031 * @param o Object to store, of type LayoutSlip 032 * @return Element containing the complete info 033 */ 034 @Override 035 public Element store(Object o) { 036 037 LayoutSlipView pv = (LayoutSlipView) o; 038 LayoutSlip p = pv.getSlip(); 039 040 Element element = new Element("layoutSlip"); 041 042 // include attributes 043 element.setAttribute("ident", p.getName()); 044 element.setAttribute("slipType", tTypeEnumMap.outputFromEnum(p.getTurnoutType())); 045 046 element.setAttribute("hidden", "" + (pv.isHidden() ? "yes" : "no")); 047 element.setAttribute("disabled", "" + (p.isDisabled() ? "yes" : "no")); 048 element.setAttribute("disableWhenOccupied", "" + (p.isDisabledWhenOccupied() ? "yes" : "no")); 049 050 if (p.showToolTip()) { 051 element.setAttribute("showtooltip", "yes"); 052 } 053 054 Point2D coords = pv.getCoordsCenter(); 055 element.setAttribute("xcen", "" + coords.getX()); 056 element.setAttribute("ycen", "" + coords.getY()); 057 coords = pv.getCoordsA(); 058 element.setAttribute("xa", "" + coords.getX()); 059 element.setAttribute("ya", "" + coords.getY()); 060 coords = pv.getCoordsB(); 061 element.setAttribute("xb", "" + coords.getX()); 062 element.setAttribute("yb", "" + coords.getY()); 063 064 if (!p.getTurnoutName().isEmpty()) { 065 element.addContent(new Element("turnout").addContent(p.getTurnoutName())); 066 } 067 068 if (!p.getTurnoutBName().isEmpty()) { 069 element.addContent(new Element("turnoutB").addContent(p.getTurnoutBName())); 070 } 071 072 if (!p.getBlockName().isEmpty()) { 073 element.setAttribute("blockname", p.getBlockName()); 074 } 075 // Only save these if they're different from block A 076 if (!p.getBlockBName().isEmpty() && (!p.getBlockBName().equals(p.getBlockName()))) { 077 element.setAttribute("blockbname", p.getBlockBName()); 078 } 079 if (!p.getBlockCName().isEmpty() && (!p.getBlockCName().equals(p.getBlockName()))) { 080 element.setAttribute("blockcname", p.getBlockCName()); 081 } 082 if (!p.getBlockDName().isEmpty() && (!p.getBlockDName().equals(p.getBlockName()))) { 083 element.setAttribute("blockdname", p.getBlockDName()); 084 } 085 086 if (p.getConnectA() != null) { 087 element.setAttribute("connectaname", ((TrackSegment) p.getConnectA()).getId()); 088 } 089 if (p.getConnectB() != null) { 090 element.setAttribute("connectbname", ((TrackSegment) p.getConnectB()).getId()); 091 } 092 if (p.getConnectC() != null) { 093 element.setAttribute("connectcname", ((TrackSegment) p.getConnectC()).getId()); 094 } 095 if (p.getConnectD() != null) { 096 element.setAttribute("connectdname", ((TrackSegment) p.getConnectD()).getId()); 097 } 098 099 if (!p.getSignalA1Name().isEmpty()) { 100 element.addContent(new Element("signala1name").addContent(p.getSignalA1Name())); 101 } 102 if (!p.getSignalB1Name().isEmpty()) { 103 element.addContent(new Element("signalb1name").addContent(p.getSignalB1Name())); 104 } 105 if (!p.getSignalC1Name().isEmpty()) { 106 element.addContent(new Element("signalc1name").addContent(p.getSignalC1Name())); 107 } 108 if (!p.getSignalD1Name().isEmpty()) { 109 element.addContent(new Element("signald1name").addContent(p.getSignalD1Name())); 110 } 111 if (!p.getSignalA2Name().isEmpty()) { 112 element.addContent(new Element("signala2name").addContent(p.getSignalA2Name())); 113 } 114 if (!p.getSignalB2Name().isEmpty()) { 115 element.addContent(new Element("signalb2name").addContent(p.getSignalB2Name())); 116 } 117 if (!p.getSignalC2Name().isEmpty()) { 118 element.addContent(new Element("signalc2name").addContent(p.getSignalC2Name())); 119 } 120 if (!p.getSignalD2Name().isEmpty()) { 121 element.addContent(new Element("signald2name").addContent(p.getSignalD2Name())); 122 } 123 124 if (!p.getSignalAMastName().isEmpty()) { 125 element.addContent(new Element("signalAMast").addContent(p.getSignalAMastName())); 126 } 127 128 if (!p.getSignalBMastName().isEmpty()) { 129 element.addContent(new Element("signalBMast").addContent(p.getSignalBMastName())); 130 } 131 if (!p.getSignalCMastName().isEmpty()) { 132 element.addContent(new Element("signalCMast").addContent(p.getSignalCMastName())); 133 } 134 if (!p.getSignalDMastName().isEmpty()) { 135 element.addContent(new Element("signalDMast").addContent(p.getSignalDMastName())); 136 } 137 138 if (!p.getSensorAName().isEmpty()) { 139 element.addContent(new Element("sensorA").addContent(p.getSensorAName())); 140 } 141 142 if (!p.getSensorBName().isEmpty()) { 143 element.addContent(new Element("sensorB").addContent(p.getSensorBName())); 144 } 145 if (!p.getSensorCName().isEmpty()) { 146 element.addContent(new Element("sensorC").addContent(p.getSensorCName())); 147 } 148 if (!p.getSensorDName().isEmpty()) { 149 element.addContent(new Element("sensorD").addContent(p.getSensorDName())); 150 } 151 152 Element states = new Element("states"); 153 Element state = new Element("A-C"); 154 state.addContent(new Element("turnout").addContent("" + p.getTurnoutState(LayoutSlip.STATE_AC))); 155 state.addContent(new Element("turnoutB").addContent("" + p.getTurnoutBState(LayoutSlip.STATE_AC))); 156 states.addContent(state); 157 158 state = new Element("A-D"); 159 state.addContent(new Element("turnout").addContent("" + p.getTurnoutState(LayoutSlip.STATE_AD))); 160 state.addContent(new Element("turnoutB").addContent("" + p.getTurnoutBState(LayoutSlip.STATE_AD))); 161 states.addContent(state); 162 163 state = new Element("B-D"); 164 state.addContent(new Element("turnout").addContent("" + p.getTurnoutState(LayoutSlip.STATE_BD))); 165 state.addContent(new Element("turnoutB").addContent("" + p.getTurnoutBState(LayoutSlip.STATE_BD))); 166 states.addContent(state); 167 168 if (p.getSlipType() == LayoutSlip.TurnoutType.DOUBLE_SLIP) { 169 state = new Element("B-C"); 170 state.addContent(new Element("turnout").addContent("" + p.getTurnoutState(LayoutSlip.STATE_BC))); 171 state.addContent(new Element("turnoutB").addContent("" + p.getTurnoutBState(LayoutSlip.STATE_BC))); 172 states.addContent(state); 173 } 174 element.addContent(states); 175 storeLogixNG_Data(pv, element); 176 addClass(element); 177 return element; 178 } 179 180 @Override 181 public boolean load(Element shared, Element perNode) { 182 log.error("Invalid method called"); 183 return false; 184 } 185 186 /** 187 * Load, starting with the LayoutSlip element, then all the other data 188 * 189 * @param element Top level Element to unpack. 190 * @param o LayoutEditor as an Object 191 */ 192 @Override 193 public void load(Element element, Object o) { 194 // create the objects 195 LayoutEditor p = (LayoutEditor) o; 196 197 // get center point 198 String name = element.getAttribute("ident").getValue(); 199 double x = 0.0; 200 double y = 0.0; 201 try { 202 x = element.getAttribute("xcen").getFloatValue(); 203 y = element.getAttribute("ycen").getFloatValue(); 204 } catch (org.jdom2.DataConversionException e) { 205 log.error("failed to convert layoutslip center attribute"); 206 } 207 208 LayoutSlip.TurnoutType type = 209 tTypeEnumMap.inputFromAttribute(element.getAttribute("slipType")); 210 211 // create the new LayoutSlip 212 LayoutSlip l; 213 LayoutSlipView lv; 214 215 switch(type) { 216 case DOUBLE_SLIP : 217 LayoutDoubleSlip lds = new LayoutDoubleSlip(name, p); 218 l = lds; 219 lv = new LayoutDoubleSlipView(lds, new Point2D.Double(x, y), 0.0, p); 220 break; 221 case SINGLE_SLIP : 222 LayoutSingleSlip lss = new LayoutSingleSlip(name, p); 223 l = lss; 224 lv = new LayoutSingleSlipView(lss, new Point2D.Double(x, y), 0.0, p); 225 break; 226 default: 227 log.error("can't create slip {} with type {}", name, type); 228 return; // without creating 229 } 230 231 p.addLayoutTrack(l, lv); 232 233 // get remaining attributes 234 l.setTurnout(getElement(element, "turnout")); 235 l.setTurnoutB(getElement(element, "turnoutB")); 236 237 Attribute a = element.getAttribute("blockname"); 238 if (a != null) { 239 l.tBlockAName = a.getValue(); 240 } 241 a = element.getAttribute("blockbname"); 242 if (a != null) { 243 l.tBlockBName = a.getValue(); 244 } 245 a = element.getAttribute("blockcname"); 246 if (a != null) { 247 l.tBlockCName = a.getValue(); 248 } 249 a = element.getAttribute("blockdname"); 250 if (a != null) { 251 l.tBlockDName = a.getValue(); 252 } 253 254 a = element.getAttribute("connectaname"); 255 if (a != null) { 256 l.connectAName = a.getValue(); 257 } 258 a = element.getAttribute("connectbname"); 259 if (a != null) { 260 l.connectBName = a.getValue(); 261 } 262 a = element.getAttribute("connectcname"); 263 if (a != null) { 264 l.connectCName = a.getValue(); 265 } 266 a = element.getAttribute("connectdname"); 267 if (a != null) { 268 l.connectDName = a.getValue(); 269 } 270 271 l.setSignalA1Name(getElement(element, "signala1name")); 272 l.setSignalB1Name(getElement(element, "signalb1name")); 273 l.setSignalC1Name(getElement(element, "signalc1name")); 274 l.setSignalD1Name(getElement(element, "signald1name")); 275 276 l.setSignalA2Name(getElement(element, "signala2name")); 277 l.setSignalB2Name(getElement(element, "signalb2name")); 278 l.setSignalC2Name(getElement(element, "signalc2name")); 279 l.setSignalD2Name(getElement(element, "signald2name")); 280 281 try { 282 l.setDisabled(element.getAttribute("disabled").getBooleanValue()); 283 } catch (DataConversionException e1) { 284 log.warn("unable to convert layout turnout disabled attribute"); 285 } catch (NullPointerException e) { // considered normal if the attribute is not present 286 } 287 try { 288 l.setDisableWhenOccupied(element.getAttribute("disableWhenOccupied").getBooleanValue()); 289 } catch (DataConversionException e1) { 290 log.warn("unable to convert layout turnout disableWhenOccupied attribute"); 291 } catch (NullPointerException e) { // considered normal if the attribute is not present 292 } 293 try { 294 lv.setHidden(element.getAttribute("hidden").getBooleanValue()); 295 } catch (DataConversionException e1) { 296 log.warn("unable to convert layout turnout hidden attribute"); 297 } catch (NullPointerException e) { // considered normal if the attribute is not present 298 } 299 300 l.setShowToolTip(false); 301 a = element.getAttribute("showtooltip"); 302 if (a != null) { 303 if ("yes".equals(a.getValue())) { 304 l.setShowToolTip(true); 305 } 306 } 307 308 try { 309 x = element.getAttribute("xa").getFloatValue(); 310 y = element.getAttribute("ya").getFloatValue(); 311 lv.setCoordsA(new Point2D.Double(x, y)); 312 } catch (org.jdom2.DataConversionException e) { 313 log.error("failed to convert LayoutSlip a coords attribute"); 314 } 315 try { 316 x = element.getAttribute("xb").getFloatValue(); 317 y = element.getAttribute("yb").getFloatValue(); 318 lv.setCoordsB(new Point2D.Double(x, y)); 319 } catch (org.jdom2.DataConversionException e) { 320 log.error("failed to convert LayoutSlip b coords attribute"); 321 } 322 323 l.setSignalAMast(getElement(element, "signalAMast")); 324 l.setSignalBMast(getElement(element, "signalBMast")); 325 l.setSignalCMast(getElement(element, "signalCMast")); 326 l.setSignalDMast(getElement(element, "signalDMast")); 327 328 l.setSensorA(getElement(element, "sensorA")); 329 l.setSensorB(getElement(element, "sensorB")); 330 l.setSensorC(getElement(element, "sensorC")); 331 l.setSensorD(getElement(element, "sensorD")); 332 333 if (element.getChild("states") != null) { 334 Element state = element.getChild("states"); 335 if (state.getChild("A-C") != null) { 336 Element ac = state.getChild("A-C"); 337 l.setTurnoutStates(LayoutSlip.STATE_AC, 338 ac.getChild("turnout").getText(), 339 ac.getChild("turnoutB").getText()); 340 } 341 if (state.getChild("A-D") != null) { 342 Element ad = state.getChild("A-D"); 343 l.setTurnoutStates(LayoutSlip.STATE_AD, 344 ad.getChild("turnout").getText(), 345 ad.getChild("turnoutB").getText()); 346 } 347 if (state.getChild("B-D") != null) { 348 Element bd = state.getChild("B-D"); 349 l.setTurnoutStates(LayoutSlip.STATE_BD, 350 bd.getChild("turnout").getText(), 351 bd.getChild("turnoutB").getText()); 352 } 353 if (state.getChild("B-C") != null) { 354 Element bc = state.getChild("B-C"); 355 l.setTurnoutStates(LayoutSlip.STATE_BC, 356 bc.getChild("turnout").getText(), 357 bc.getChild("turnoutB").getText()); 358 } 359 } 360 361 loadLogixNG_Data(lv, element); 362 } 363 364 String getElement(Element el, String child) { 365 if (el.getChild(child) != null) { 366 return el.getChild(child).getText(); 367 } 368 return ""; 369 } 370 371 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LayoutSlipViewXml.class); 372}