001package jmri.jmrit.swing.meter.configurexml; 002 003import java.awt.GraphicsEnvironment; 004import java.util.List; 005import java.util.UUID; 006 007import jmri.InstanceManager; 008import jmri.Meter; 009import jmri.MeterManager; 010import jmri.configurexml.JmriConfigureXmlException; 011import jmri.jmrit.swing.meter.MeterFrame; 012import jmri.jmrit.swing.meter.MeterFrameManager; 013 014import org.jdom2.Attribute; 015import org.jdom2.Element; 016 017import javax.annotation.Nonnull; 018 019/** 020 * Stores MeterFrames to the panel file. 021 * @author Daniel Bergqvist Copyright (c) 2020 022 */ 023public class MeterFrameManagerXml extends jmri.configurexml.AbstractXmlAdapter { 024 025 private final EnumIO<MeterFrame.Unit> unitEnumMap = new EnumIoNames<>(MeterFrame.Unit.class); 026 027 public MeterFrameManagerXml() { 028 } 029 030 @Override 031 public Element store(Object o) { 032 Element meterFrames = new Element("meterFrames"); 033 setStoreElementClass(meterFrames); 034 035 var frames = MeterFrameManager.getInstance().getMeterFrames(); 036 if (frames.isEmpty()) return null; 037 038 boolean empty = true; 039 for (MeterFrame frame : frames) { 040 var meterElement = storeMeterFrame(frame); 041 if (meterElement == null) continue; 042 empty = false; 043 meterFrames.addContent(meterElement); 044 } 045 046 if (empty) return null; 047 return meterFrames; 048 } 049 050 public Element storeMeterFrame(MeterFrame frame) { 051 Element e = new Element("meterFrame"); 052 053 Element e2 = new Element("uuid"); 054 e2.addContent(frame.getUUID().toString()); 055 e.addContent(e2); 056 057 e2 = new Element("meter"); 058 if (frame.getMeter() == null) { 059 return null; // apparently user did not assign a real world meter; do not save 060 } 061 e2.addContent(frame.getMeter().getSystemName()); // this should be a NamedBeanHandle 062 e.addContent(e2); 063 064 e.setAttribute("unit", unitEnumMap.outputFromEnum(frame.getUnit())); 065 e.setAttribute("integer-digits", Integer.toString(frame.getNumIntegerDigits())); 066 e.setAttribute("decimal-digits", Integer.toString(frame.getNumDecimalDigits())); 067 e.setAttribute("x", Integer.toString(frame.getX())); 068 e.setAttribute("y", Integer.toString(frame.getY())); 069 e.setAttribute("width", Integer.toString(frame.getWidth())); 070 e.setAttribute("height", Integer.toString(frame.getHeight())); 071 072 return e; 073 } 074 075 /** 076 * Subclass provides implementation to create the correct top element, 077 * including the type information. Default implementation is to use the 078 * local class here. 079 * 080 * @param meterFrames The top-level element being created 081 */ 082 public void setStoreElementClass(Element meterFrames) { 083 meterFrames.setAttribute("class", this.getClass().getName()); // NOI18N 084 } 085 086 /** {@inheritDoc} */ 087 @Override 088 public boolean load(@Nonnull Element shared, Element perNode) throws JmriConfigureXmlException { 089 // Don't create frames if headless 090 if (GraphicsEnvironment.isHeadless()) return true; 091 092 List<Element> frames = shared.getChildren("meterFrame"); 093 094 for (Element elem : frames) { 095 String uuidStr = elem.getChild("uuid").getText(); 096 String meterSystemName = elem.getChild("meter").getText(); // This should be a NamedBeanHandle, but may not exist yet 097 Meter meter = InstanceManager.getDefault(MeterManager.class).getBySystemName(meterSystemName); 098 UUID uuid = UUID.fromString(uuidStr); 099 MeterFrame frame = MeterFrameManager.getInstance().getByUUID(uuid); 100 if (frame == null) { 101 log.debug("creating frame for uuid: {}, selected meter: {}", uuidStr, meterSystemName); 102 frame = new MeterFrame(uuid); 103 frame.initComponents(); 104 } 105 if (meter != null) { 106 frame.setMeter(meter); 107 } else { 108 log.debug("selected meter '{}' not (yet) defined, remembering for later.", meterSystemName); 109 frame.setInitialMeterName(meterSystemName); 110 } 111 112 Attribute a = elem.getAttribute("unit"); 113 if (a != null) frame.setUnit(unitEnumMap.inputFromAttribute(a)); 114 115 frame.setNumIntegerDigits(getAttributeIntegerValue(elem, "integer-digits", 3)); 116 frame.setNumDecimalDigits(getAttributeIntegerValue(elem, "decimal-digits", 0)); 117 118 frame.setLocation( 119 Integer.parseInt(elem.getAttributeValue("x")), 120 Integer.parseInt(elem.getAttributeValue("y"))); 121 frame.setSize( 122 Integer.parseInt(elem.getAttributeValue("width")), 123 Integer.parseInt(elem.getAttributeValue("height"))); 124 frame.setVisible(true); 125 } 126 127 return true; 128 } 129 130 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MeterFrameManagerXml.class); 131 132}