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        for (MeterFrame frame : MeterFrameManager.getInstance().getMeterFrames()) {
036            meterFrames.addContent(storeMeterFrame(frame));
037        }
038        
039        return meterFrames;
040    }
041    
042    public Element storeMeterFrame(MeterFrame frame) {
043        Element e = new Element("meterFrame");
044        
045        Element e2 = new Element("uuid");
046        e2.addContent(frame.getUUID().toString());
047        e.addContent(e2);
048        
049        e2 = new Element("meter");
050        if (frame.getMeter() == null) {
051            return e; // apparently user did not assign a real world meter; do not save
052        }
053        e2.addContent(frame.getMeter().getSystemName()); // this should be a NamedBeanHandle
054        e.addContent(e2);
055        
056        e.setAttribute("unit", unitEnumMap.outputFromEnum(frame.getUnit()));
057        e.setAttribute("integer-digits", Integer.toString(frame.getNumIntegerDigits()));
058        e.setAttribute("decimal-digits", Integer.toString(frame.getNumDecimalDigits()));
059        e.setAttribute("x", Integer.toString(frame.getX()));
060        e.setAttribute("y", Integer.toString(frame.getY()));
061        e.setAttribute("width", Integer.toString(frame.getWidth()));
062        e.setAttribute("height", Integer.toString(frame.getHeight()));
063        
064        return e;
065    }
066    
067    /**
068     * Subclass provides implementation to create the correct top element,
069     * including the type information. Default implementation is to use the
070     * local class here.
071     *
072     * @param meterFrames The top-level element being created
073     */
074    public void setStoreElementClass(Element meterFrames) {
075        meterFrames.setAttribute("class", this.getClass().getName());  // NOI18N
076    }
077    
078    /** {@inheritDoc} */
079    @Override
080    public boolean load(@Nonnull Element shared, Element perNode) throws JmriConfigureXmlException {
081        // Don't create frames if headless
082        if (GraphicsEnvironment.isHeadless()) return true;
083        
084        List<Element> frames = shared.getChildren("meterFrame");
085        
086        for (Element elem : frames) {
087            String uuidStr = elem.getChild("uuid").getText();
088            String meterSystemName = elem.getChild("meter").getText();      // This should be a NamedBeanHandle, but may not exist yet
089            Meter meter = InstanceManager.getDefault(MeterManager.class).getBySystemName(meterSystemName);
090            UUID uuid = UUID.fromString(uuidStr);
091            MeterFrame frame = MeterFrameManager.getInstance().getByUUID(uuid);
092            if (frame == null) {
093                log.debug("creating frame for uuid: {}, selected meter: {}", uuidStr, meterSystemName);
094                frame = new MeterFrame(uuid);
095                frame.initComponents();
096            }
097            if (meter != null) {
098                frame.setMeter(meter);
099            } else {
100                log.debug("selected meter '{}' not (yet) defined, remembering for later.", meterSystemName);                
101                frame.setInitialMeterName(meterSystemName);
102            }
103            
104            Attribute a = elem.getAttribute("unit");
105            if (a != null) frame.setUnit(unitEnumMap.inputFromAttribute(a));
106            
107            frame.setNumIntegerDigits(getAttributeIntegerValue(elem, "integer-digits", 3));
108            frame.setNumDecimalDigits(getAttributeIntegerValue(elem, "decimal-digits", 0));
109            
110            frame.setLocation(
111                    Integer.parseInt(elem.getAttributeValue("x")),
112                    Integer.parseInt(elem.getAttributeValue("y")));
113            frame.setSize(
114                    Integer.parseInt(elem.getAttributeValue("width")),
115                    Integer.parseInt(elem.getAttributeValue("height")));
116            frame.setVisible(true);
117        }
118        
119        return true;
120    }
121
122    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MeterFrameManagerXml.class);
123
124}