001package jmri.jmrit.display.configurexml; 002 003import java.awt.Color; 004import java.util.HashMap; 005import java.util.List; 006 007import jmri.configurexml.JmriConfigureXmlException; 008import jmri.jmrit.catalog.NamedIcon; 009import jmri.jmrit.display.*; 010 011import org.jdom2.Attribute; 012import org.jdom2.Element; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016/** 017 * Handle configuration for display.SensorIcon objects. 018 * 019 * @author Bob Jacobsen Copyright: Copyright (c) 2002 020 */ 021public class SensorIconXml extends PositionableLabelXml { 022 023 static final HashMap<String, String> _nameMap = new HashMap<>(); 024 025 public SensorIconXml() { 026 // map previous store names to property key names 027 _nameMap.put("active", "SensorStateActive"); 028 _nameMap.put("inactive", "SensorStateInactive"); 029 _nameMap.put("unknown", "BeanStateUnknown"); 030 _nameMap.put("inconsistent", "BeanStateInconsistent"); 031 } 032 033 /** 034 * Default implementation for storing the contents of a SensorIcon. 035 * 036 * @param o Object to store, of type SensorIcon 037 * @return Element containing the complete info 038 */ 039 @Override 040 public Element store(Object o) { 041 SensorIcon p = (SensorIcon) o; 042 if (!p.isActive()) { 043 return null; // if flagged as inactive, don't store 044 } 045 Element element = new Element("sensoricon"); 046 element.setAttribute("sensor", p.getNamedSensor().getName()); 047 storeCommonAttributes(p, element); 048 element.setAttribute("momentary", p.getMomentary() ? "true" : "false"); 049 element.setAttribute("icon", p.isIcon() ? "yes" : "no"); 050 051 storeIconInfo(p, element); 052 storeTextInfo(p, element); 053 054 storeLogixNG_Data(p, element); 055 056 element.setAttribute("class", "jmri.jmrit.display.configurexml.SensorIconXml"); 057 return element; 058 } 059 060 protected void storeTextInfo(SensorIcon p, Element element) { 061 if (p.getText() == null) { 062 String s = p.getOriginalText(); 063 if (s != null && s.length() > 0) { 064 element.setAttribute("text", s); 065 } else if (p.isText()) { 066 element.setAttribute("text", ""); 067 } else { 068 return; 069 } 070 } else { 071 element.setAttribute("text", p.getText()); 072 } 073 // get iconic overlay text info 074 super.storeTextInfo(p, element); 075 // get state textual info 076 Element textElement = new Element("activeText"); 077 if (p.getActiveText() != null) { 078 textElement.setAttribute("text", p.getActiveText()); 079 } 080 081 // always write text color 082 textElement.setAttribute("red", "" + p.getTextActive().getRed()); 083 textElement.setAttribute("green", "" + p.getTextActive().getGreen()); 084 textElement.setAttribute("blue", "" + p.getTextActive().getBlue()); 085 086 if (p.getBackgroundActive() != null) { 087 textElement.setAttribute("redBack", "" + p.getBackgroundActive().getRed()); 088 textElement.setAttribute("greenBack", "" + p.getBackgroundActive().getGreen()); 089 textElement.setAttribute("blueBack", "" + p.getBackgroundActive().getBlue()); 090 } 091 element.addContent(textElement); 092 textElement = new Element("inactiveText"); 093 if (p.getInactiveText() != null) { 094 textElement.setAttribute("text", p.getInactiveText()); 095 } 096 097 // always write text color 098 textElement.setAttribute("red", "" + p.getTextInActive().getRed()); 099 textElement.setAttribute("green", "" + p.getTextInActive().getGreen()); 100 textElement.setAttribute("blue", "" + p.getTextInActive().getBlue()); 101 102 if (p.getBackgroundInActive() != null) { 103 textElement.setAttribute("redBack", "" + p.getBackgroundInActive().getRed()); 104 textElement.setAttribute("greenBack", "" + p.getBackgroundInActive().getGreen()); 105 textElement.setAttribute("blueBack", "" + p.getBackgroundInActive().getBlue()); 106 } 107 element.addContent(textElement); 108 109 textElement = new Element("unknownText"); 110 111 if (p.getUnknownText() != null) { 112 textElement.setAttribute("text", p.getUnknownText()); 113 } 114 115 // always write text color 116 textElement.setAttribute("red", "" + p.getTextUnknown().getRed()); 117 textElement.setAttribute("green", "" + p.getTextUnknown().getGreen()); 118 textElement.setAttribute("blue", "" + p.getTextUnknown().getBlue()); 119 120 if (p.getBackgroundUnknown() != null) { 121 textElement.setAttribute("redBack", "" + p.getBackgroundUnknown().getRed()); 122 textElement.setAttribute("greenBack", "" + p.getBackgroundUnknown().getGreen()); 123 textElement.setAttribute("blueBack", "" + p.getBackgroundUnknown().getBlue()); 124 } 125 element.addContent(textElement); 126 127 textElement = new Element("inconsistentText"); 128 if (p.getInconsistentText() != null) { 129 textElement.setAttribute("text", p.getInconsistentText()); 130 } 131 132 // always write text color 133 textElement.setAttribute("red", "" + p.getTextInconsistent().getRed()); 134 textElement.setAttribute("green", "" + p.getTextInconsistent().getGreen()); 135 textElement.setAttribute("blue", "" + p.getTextInconsistent().getBlue()); 136 137 if (p.getBackgroundInconsistent() != null) { 138 textElement.setAttribute("redBack", "" + p.getBackgroundInconsistent().getRed()); 139 textElement.setAttribute("greenBack", "" + p.getBackgroundInconsistent().getGreen()); 140 textElement.setAttribute("blueBack", "" + p.getBackgroundInconsistent().getBlue()); 141 } 142 element.addContent(textElement); 143 } 144 145 protected void storeIconInfo(SensorIcon p, Element element) { 146 element.addContent(storeIcon("active", p.getIcon("SensorStateActive"))); 147 element.addContent(storeIcon("inactive", p.getIcon("SensorStateInactive"))); 148 element.addContent(storeIcon("unknown", p.getIcon("BeanStateUnknown"))); 149 element.addContent(storeIcon("inconsistent", p.getIcon("BeanStateInconsistent"))); 150 Element elem = new Element("iconmaps"); 151 String family = p.getFamily(); 152 if (family != null) { 153 elem.setAttribute("family", family); 154 } 155 element.addContent(elem); 156 } 157 158 boolean _icon; 159 160 /** 161 * Create a PositionableLabel, then add to a target JLayeredPane. 162 * 163 * @param element Top level Element to unpack. 164 * @param o an Editor as an Object 165 * @throws JmriConfigureXmlException when a error prevents creating the objects as as 166 * required by the input XML 167 */ 168 @Override 169 public void load(Element element, Object o) throws JmriConfigureXmlException { 170 Editor ed = (Editor) o; 171 SensorIcon l; 172 String name; 173 Attribute attr = element.getAttribute("sensor"); 174 if (attr == null) { 175 log.error("incorrect information for sensor; must use sensor name"); 176 ed.loadFailed(); 177 return; 178 } else { 179 name = attr.getValue(); 180 } 181 _icon = true; 182 if (element.getAttribute("icon") != null) { 183 String yesno = element.getAttribute("icon").getValue(); 184 if ((yesno != null) && (!yesno.equals(""))) { 185 if (yesno.equals("yes")) { 186 _icon = true; 187 } else if (yesno.equals("no")) { 188 _icon = false; 189 } 190 } 191 } 192 193 if (_icon) { 194 l = new SensorIcon(new NamedIcon("resources/icons/smallschematics/tracksegments/circuit-error.gif", 195 "resources/icons/smallschematics/tracksegments/circuit-error.gif"), 196 ed); 197 } else { 198 l = new SensorIcon(" ", ed); 199 } 200 int rotation = 0; 201 try { 202 rotation = element.getAttribute("rotate").getIntValue(); 203 } catch (org.jdom2.DataConversionException e) { 204 } catch (NullPointerException e) { // considered normal if the attributes are not present 205 } 206 207 if (loadSensorIcon("active", rotation, l, element, name, ed) == null) { 208 return; 209 } 210 if (loadSensorIcon("inactive", rotation, l, element, name, ed) == null) { 211 return; 212 } 213 if (loadSensorIcon("unknown", rotation, l, element, name, ed) == null) { 214 return; 215 } 216 if (loadSensorIcon("inconsistent", rotation, l, element, name, ed) == null) { 217 return; 218 } 219 Element elem = element.getChild("iconmaps"); 220 if (elem != null) { 221 attr = elem.getAttribute("family"); 222 if (attr != null) { 223 l.setFamily(attr.getValue()); 224 } 225 } 226 227 Attribute a = element.getAttribute("momentary"); 228 if ((a != null) && a.getValue().equals("true")) { 229 l.setMomentary(true); 230 } else { 231 l.setMomentary(false); 232 } 233 234 loadTextInfo(l, element); 235 l.setSensor(name); 236 237 try { 238 ed.putItem(l); 239 } catch (Positionable.DuplicateIdException e) { 240 throw new JmriConfigureXmlException("Positionable id is not unique", e); 241 } 242 243 loadLogixNG_Data(l, element); 244 245 // load individual item's option settings after editor has set its global settings 246 loadCommonAttributes(l, Editor.SENSORS, element); 247 if (l.isIcon() && l.getText()!=null) { 248 l.setOpaque(false); 249 } 250 } 251 252 private NamedIcon loadSensorIcon(String state, int rotation, SensorIcon l, 253 Element element, String name, Editor ed) { 254 String msg = "SensorIcon \"" + name + "\": icon \"" + state + "\" "; 255 // loadIcon gets icon as an element 256 NamedIcon icon = loadIcon(l, state, element, msg, ed); 257 if (icon == null && _icon) { 258 // old config files may define icons as attributes 259 String iconName; 260 if (element.getAttribute(state) != null 261 && !(iconName = element.getAttribute(state).getValue()).equals("")) { 262 263 icon = NamedIcon.getIconByName(iconName); 264 if (icon == null) { 265 icon = ed.loadFailed(msg, iconName); 266 if (icon == null) { 267 log.info("{} removed for url= {}", msg, iconName); 268 } 269 } else { 270 icon.setRotation(rotation, l); 271 } 272 } else { 273 log.warn("did not locate {} icon file for {}", state, name); 274 } 275 } 276 if (icon == null) { 277 log.info("{} removed", msg); 278 } else { 279 l.setIcon(_nameMap.get(state), icon); 280 } 281 return icon; 282 } 283 284 void loadTextInfo(SensorIcon l, Element element) { 285 super.loadTextInfo(l, element); 286 287 loadSensorTextState("Active", l, element); 288 loadSensorTextState("InActive", l, element); 289 loadSensorTextState("Unknown", l, element); 290 loadSensorTextState("Inconsistent", l, element); 291 if (element.getAttribute("text") != null) { 292 l.setOriginalText(element.getAttribute("text").getValue()); 293 l.setText(element.getAttribute("text").getValue()); 294 } 295 } 296 297 private void loadSensorTextState(String state, SensorIcon l, Element element) { 298 String name = null; 299 Color clrText = null; 300 Color clrBackground = null; 301 List<Element> textList = element.getChildren(state.toLowerCase() + "Text"); 302 if (log.isDebugEnabled()) { 303 log.debug("Found {} {}Text objects", textList.size(), state); 304 } 305 if (textList.size() > 0) { 306 Element elem = textList.get(0); 307 try { 308 name = elem.getAttribute("text").getValue(); 309 } catch (NullPointerException e) { // considered normal if the attributes are not present 310 } 311 try { 312 int red = elem.getAttribute("red").getIntValue(); 313 int blue = elem.getAttribute("blue").getIntValue(); 314 int green = elem.getAttribute("green").getIntValue(); 315 clrText = new Color(red, green, blue); 316 } catch (org.jdom2.DataConversionException e) { 317 log.warn("Could not parse color attributes!"); 318 } catch (NullPointerException e) { // considered normal if the attributes are not present 319 } 320 try { 321 int red = elem.getAttribute("redBack").getIntValue(); 322 int blue = elem.getAttribute("blueBack").getIntValue(); 323 int green = elem.getAttribute("greenBack").getIntValue(); 324 clrBackground = new Color(red, green, blue); 325 } catch (org.jdom2.DataConversionException e) { 326 log.warn("Could not parse color attributes!"); 327 } catch (NullPointerException e) { // considered normal if the attributes are not present 328 } 329 330 } else { 331 if (element.getAttribute(state.toLowerCase()) != null) { 332 name = element.getAttribute(state.toLowerCase()).getValue(); 333 } 334 try { 335 int red = element.getAttribute("red" + state).getIntValue(); 336 int blue = element.getAttribute("blue" + state).getIntValue(); 337 int green = element.getAttribute("green" + state).getIntValue(); 338 clrText = new Color(red, green, blue); 339 } catch (org.jdom2.DataConversionException e) { 340 log.warn("Could not parse color attributes!"); 341 } catch (NullPointerException e) { // considered normal if the attributes are not present 342 } 343 try { 344 int red = element.getAttribute("red" + state + "Back").getIntValue(); 345 int blue = element.getAttribute("blue" + state + "Back").getIntValue(); 346 int green = element.getAttribute("green" + state + "Back").getIntValue(); 347 clrBackground = new Color(red, green, blue); 348 } catch (org.jdom2.DataConversionException e) { 349 log.warn("Could not parse color attributes!"); 350 } catch (NullPointerException e) { // considered normal if the attributes are not present 351 } 352 } 353 if (state.equals("Active")) { 354 if (name != null) { 355 l.setActiveText(name); 356 } 357 if (clrText != null) { 358 l.setTextActive(clrText); 359 } 360 if (clrBackground != null) { 361 l.setBackgroundActive(clrBackground); 362 } 363 } else if (state.equals("InActive")) { 364 if (name != null) { 365 l.setInactiveText(name); 366 } 367 if (clrText != null) { 368 l.setTextInActive(clrText); 369 } 370 if (clrBackground != null) { 371 l.setBackgroundInActive(clrBackground); 372 } 373 } else if (state.equals("Unknown")) { 374 if (name != null) { 375 l.setUnknownText(name); 376 } 377 if (clrText != null) { 378 l.setTextUnknown(clrText); 379 } 380 if (clrBackground != null) { 381 l.setBackgroundUnknown(clrBackground); 382 } 383 } else if (state.equals("Inconsistent")) { 384 if (name != null) { 385 l.setInconsistentText(name); 386 } 387 if (clrText != null) { 388 l.setTextInconsistent(clrText); 389 } 390 if (clrBackground != null) { 391 l.setBackgroundInconsistent(clrBackground); 392 } 393 } 394 } 395 396 private final static Logger log = LoggerFactory.getLogger(SensorIconXml.class); 397 398}